GithubHelp home page GithubHelp logo

Comments (2)

bugoverdose avatar bugoverdose commented on August 10, 2024 2

기본적으로 아래와 같은 PieceEntity 데이터의 리스트를 Map<Position, Piece> 형식으로 변환해야 한다고 가정하자. 개별 PieceEntity 객체에는 PositionPiece 객체를 생성하는 데 필요한 모든 정보가 담겨있다.

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.

bugoverdose avatar bugoverdose commented on August 10, 2024 2

다만, 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)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.