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 color;
String carCode;
}
Now I need to map the bumper cars to a List of DistGroup objects, which each contains the properties size, color and a List of car codes.
class DistGroup {
int size;
Color color;
List<String> carCodes;
void addCarCodes(List<String> carCodes) {
this.carCodes.addAll(carCodes);
}
}
For example,
[
BumperCar(size=3, color=yellow, carCode=Q4M),
BumperCar(size=3, color=yellow, carCode=T5A),
BumperCar(size=3, color=red, carCode=6NR)
]
should result in:
[
DistGroup(size=3, color=yellow, carCodes=[ Q4M, T5A ]),
DistGroup(size=3, color=red, carCodes=[ 6NR ])
]
I tried the following, which actually does what I want it to do. But the problem is that it materializes the intermediate result (into a Map) and I also think that it can be done at once (perhaps using mapping or collectingAndThen or reducing or something), resulting in more elegant code.
List<BumperCar> bumperCars = …;
Map<SizeColorCombination, List<BumperCar>> map = bumperCars.stream()
.collect(groupingBy(t -> new SizeColorCombination(t.getSize(), t.getColor())));
List<DistGroup> distGroups = map.entrySet().stream()
.map(t -> {
DistGroup d = new DistGroup(t.getKey().getSize(), t.getKey().getColor());
d.addCarCodes(t.getValue().stream()
.map(BumperCar::getCarCode)
.collect(toList()));
return d;
})
.collect(toList());
How can I get the desired result without using a variable for an intermediate result?
Edit: How can I get the desired result without materializing the intermediate result? I am merely looking for a way which does not materialize the intermediate result, at least not on the surface. That means that I prefer not to use something like this:
something.stream()
.collect(…) // Materializing
.stream()
.collect(…); // Materializing second time
Of course, if this is possible.
Note that I omitted getters and constructors for brevity. You may also assume that equals and hashCode methods are properly implemented. Also note that I'm using the SizeColorCombination which I use as group-by key. This class obviously contains the properties size and color. Classes like Tuple, Pair, Entry or any other class representing a combination of two arbitrary values may also be used.
Edit: Also note that an ol' skool for loop can be used instead, of course, but that is not in the scope of this question.
groupingBy()does group the values into aListby default sotoList()may be omitted