Comments (2)
기본적으로 아래와 같은 PieceEntity
데이터의 리스트를 Map<Position, Piece>
형식으로 변환해야 한다고 가정하자. 개별 PieceEntity
객체에는 Position
과 Piece
객체를 생성하는 데 필요한 모든 정보가 담겨있다.
private final List<PieceEntity> PIECE_ENTITIES = List.of(
new PieceEntity("a1", "PAWN", "WHITE"),
new PieceEntity("c3", "KNIGHT", "BLACK"),
new PieceEntity("e3", "QUEEN", "BLACK"));
private final Map<Position, Piece> expected = new HashMap<>(){{
put(Position.of("a1"), Piece.of(Color.WHITE, PieceType.PAWN));
put(Position.of("c3"), Piece.of(Color.BLACK, PieceType.KNIGHT));
put(Position.of("e3"), Piece.of(Color.BLACK, PieceType.QUEEN));
}};
일단 스트림이 없는 경우 아래와 같이 (1) 비어있는 맵을 초기화하고, (2) for문을 통해 리스트를 돌며 초기화된 맵에 한쌍식 데이터를 추가할 수 있다. 가독성이 낮지도 않고 굉장히 표준적인 방법이라고 볼 수 있다.
@Test
void withoutStream() {
final Map<Position, Piece> actual = new HashMap<>();
for (PieceEntity pieceEntity : PIECE_ENTITIES) {
Position position = pieceEntity.getPosition();
Piece piece = pieceEntity.toModel();
actual.put(position, piece);
}
assertThat(actual).isEqualTo(expected);
}
다음은 리스트를 스트림으로 만든 후 Collector
없이 collect()
메서드를 사용하는 방법이다. 굉장히 가독성이 낮지만 기본 구조는 거의 위와 유사하다. (1) 스트림 요소를 순회하며 데이터를 담을 맵을 초기화하기 위한 함수를 전달하고, (2) 개별 데이터를 맵에 추가하기 위한 함수를 collect
의 매개변수로 전달하였다. 3번째 매개변수의 경우 병렬적으로 처리될 때 복수의 맵을 하나로 합치기 위한 기능인데, 순차 스트림으로만 사용하는 경우 아래와 같이 구실만 맞추기 위해 임의의 맵 데이터를 반환하도록 하여도 무관하다.
솔직히 아래와 같이 할 바에야 위의 방식대로 하는 것이 더 좋다고 생각한다.
@Test
void collectWithoutCollector() {
final Map<Position, Piece> actual = PIECE_ENTITIES.stream()
.collect(HashMap::new, // (1) supplier
(map, pieceEntity) -> map.put(pieceEntity.getPosition(), pieceEntity.toModel()), // (2) accumulator
(map1, map2) -> new HashMap<>() // (3) combiner
);
assertThat(actual).isEqualTo(expected);
}
다음은 리스트를 스트림으로 만든 후 Collector.toMap()
을 활용하는 방식이다. toMap()
은 스트림의 개별 요소를 통해 맵의 key 값과 value 값을 만드는 함수 두 개를 매개변수로 받는다. 사실 위의 for문에 비해 세로로는 짧아졌지만 가로로는 길어졌기 때문에 가독성이 개선되었다고 보기는 다소 어렵다고 생각한다. 다만, 맵에 데이터를 추가하기 전에 수행되어야 하는 작업이 별도로 존재하는 경우, 스트림 파이프라인에 중간연산을 추가하는 방식으로 로직을 추가할 수 있을 것이다.
@Test
void collectToMap() {
final Map<Position, Piece> actual = PIECE_ENTITIES.stream()
.collect(Collectors.toMap(PieceEntity::getPosition, PieceEntity::toModel));
assertThat(actual).isEqualTo(expected);
}
from 2022-modern-java-in-action.
다만, toMap
은 기본적으로 맵에 추가하고 싶은 모든 데이터 요소들이 하나의 컬렉션으로 모아져 있어야 하며, 맵을 구성하는 데 필요한 키-값 쌍이 개별 데이터에 담겨져 있어야 사용하기 용이하다.
아래는 억지로 toMap
을 사용하기 위해 (1) 맵에 추가하기 위한 키-값 쌍이 담긴 PositionPiecePair라는 클래스를 만들고, (2) 맵을 구성하는 모든 데이터를 굳이 하나의 리스트로 만들어서 스트림을 생성한 예제이다. 아래와 같은 코드를 작성함으로써 얻을 수 있는 이점이 그다지 보이지 않는다.
public Map<Position, Piece> initFullChessBoard() {
return initAllPieces().stream()
.collect(toMap(PositionPiecePair::position, PositionPiecePair::piece));
}
private List<PositionPiecePair> initAllPieces() {
final List<PositionPiecePair> pieces = new ArrayList<>();
pieces.addAll(initNonPawns(Color.BLACK, BLACK_NON_PAWN_INIT_RANK));
pieces.addAll(initPawns(Color.BLACK, BLACK_PAWN_INIT_RANK));
pieces.addAll(initPawns(Color.WHITE, WHITE_PAWN_INIT_RANK));
pieces.addAll(initNonPawns(Color.WHITE, WHITE_NON_PAWN_INIT_RANK));
return pieces;
}
from 2022-modern-java-in-action.
Related Issues (20)
- 컬렉션과 스트림의 차이는 뭘까? HOT 1
- 스트림은 만능일까? HOT 1
- 스트림이 게으르게 계산하면서 얻는 이점은 무엇일까? HOT 1
- 루프 퓨전이란 무엇인가? HOT 1
- 스트림 파이프라인은 무엇일까? HOT 1
- 스트림 연산은 어떻게 작동할까? HOT 1
- 쇼트서킷은 어떻게 작동하는 것일까? HOT 2
- 스트림 연산에 있어 상태가 있거나 없다는 의미가 무엇인가? HOT 2
- 무한스트림과 가변, 불변 상태 HOT 1
- Optional을 사용해야 하는 적절한 경우는 언제일까? HOT 1
- 무한 스트림의 존재 의의
- reduce를 사용하는 것이 왜 반복문보다 장점을 가지는 것일까? HOT 2
- flatMap 이란? HOT 1
- null에 안전한 스트림 생성 방법 HOT 1
- groupingBy와 partitioningBy 비교 HOT 1
- collect vs collector vs collectors (vs Collections vs Collection) 구분하기 HOT 2
- 내장 Collector의 Characteristics 파악하기 HOT 1
- reduce vs collect HOT 1
- collectionAndThen() 는 언제 사용하면 좋을까?
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from 2022-modern-java-in-action.