grouping objects java 8

前端 未结 3 1995
鱼传尺愫
鱼传尺愫 2021-01-13 09:56

I have something like the below :

public class MyClass {
private Long stackId
private Long questionId
}

A collection of say 100, where the

3条回答
  •  隐瞒了意图╮
    2021-01-13 10:37

    The straight-forward way with the Stream API involves 2 Stream pipelines:

    • The first one creates a temporary Map> of stackId to questionIds. This is done with the groupingBy(classifier, downstream) collectors where we classify per the stackId and values having the same stackId are mapped to their questionId (with mapping) and collected into a list with toList().
    • The second one converts each entry of that map into a MyOtherClass instance and collects that into a list.

    Assuming you have a constructor MyOtherClass(Long stackId, Collection questionIds), a sample code would be:

    Map> map = 
        list.stream()
            .collect(Collectors.groupingBy(
                MyClass::getStackId,
                Collectors.mapping(MyClass::getQuestionId, Collectors.toList())
            ));
    
    List result = 
        map.entrySet()
           .stream()
           .map(e -> new MyOtherClass(e.getKey(), e.getValue()))
           .collect(Collectors.toList());
    

    Using StreamEx library, you could do that in a single Stream pipeline. This library offers a pairing and first collectors. This enables to pair two collectors and perform a finisher operation on the two collected results:

    • The first one only keeps the first stackId of the grouped elements (they will all be the same, by construction)
    • The second one mapping each element into their questionId and collecting into a list.
    • The finisher operation just returns a new instance of MyOtherClass.

    Sample code:

    import static java.util.stream.Collectors.collectingAndThen;
    import static java.util.stream.Collectors.mapping;
    import static java.util.stream.Collectors.toList;
    import static one.util.streamex.MoreCollectors.first;
    import static one.util.streamex.MoreCollectors.pairing;
    
    // ...
    
    Collection result = 
        StreamEx.of(list)
                .groupingBy(
                    MyClass::getStackId,
                    pairing(
                        collectingAndThen(mapping(MyClass::getStackId, first()), Optional::get),
                        mapping(MyClass::getQuestionId, toList()),
                        MyOtherClass::new
                    )
                ).values();
    

提交回复
热议问题