How to groupBy object properties and map to another object using Java 8 Streams?

后端 未结 4 1472
梦如初夏
梦如初夏 2021-02-19 01:02

Suppose I have a group of bumper cars, which have a size, a color and an identifier (\"car code\") on their sides.

class BumperCar {
    int size;
    String col         


        
4条回答
  •  暖寄归人
    2021-02-19 01:50

    Solution-1

    Just merging the two steps into one:

    List distGroups = bumperCars.stream()
            .collect(Collectors.groupingBy(t -> new SizeColorCombination(t.getSize(), t.getColor())))
            .entrySet().stream()
            .map(t -> {
                DistGroup d = new DistGroup(t.getKey().getSize(), t.getKey().getColor());
                d.addCarCodes(t.getValue().stream().map(BumperCar::getCarCode).collect(Collectors.toList()));
                return d;
            })
            .collect(Collectors.toList());
    

    Solution-2

    Your intermediate variable would be much better if you could use groupingBy twice using both the attributes and map the values as List of codes, something like:

    Map>> sizeGroupedData = bumperCars.stream()
            .collect(Collectors.groupingBy(BumperCar::getSize,
                    Collectors.groupingBy(BumperCar::getColor,
                            Collectors.mapping(BumperCar::getCarCode, Collectors.toList()))));
    

    and simply use forEach to add to the final list as:

    List distGroups = new ArrayList<>();
    sizeGroupedData.forEach((size, colorGrouped) ->
            colorGrouped.forEach((color, carCodes) -> distGroups.add(new DistGroup(size, color, carCodes))));
    

    Note: I've updated your constructor such that it accepts the card codes list.

    DistGroup(int size, String color, List carCodes) {
        this.size = size;
        this.color = color;
        addCarCodes(carCodes);
    }
    

    Further combining the second solution into one complete statement(though I would myself favor the forEach honestly):

    List distGroups = bumperCars.stream()
            .collect(Collectors.groupingBy(BumperCar::getSize,
                    Collectors.groupingBy(BumperCar::getColor,
                            Collectors.mapping(BumperCar::getCarCode, Collectors.toList()))))
            .entrySet()
            .stream()
            .flatMap(a -> a.getValue().entrySet()
                    .stream().map(b -> new DistGroup(a.getKey(), b.getKey(), b.getValue())))
            .collect(Collectors.toList());
    

提交回复
热议问题