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
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());
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());