List<Car> carList = new ArrayList<>();
Car car = new Car();
car.setMake("Honda");
car.setYear(1998);
car.setColor("red");
carList.add(car);
car = new Car();
car.setMake("Honda");
car.setYear(2020);
car.setColor("red");
carList.add(car);
car = new Car();
car.setMake("Audi");
car.setYear(2022);
car.setColor("red");
carList.add(car);
car = new Car();
car.setMake("Toyota");
car.setYear(2021);
car.setColor("blue");
carList.add(car);
car = new Car();
car.setMake("Toyota");
car.setYear(2007);
car.setColor("blue");
carList.add(car);
How to stream and collect to a map with color as key and value has list of cars with oldest car by make? the final Map should have
{
"red": [
{
"make": "Honda",
"year": "1998"
},
{
"make": "Audi",
"year": "2022"
}
],
"blue": [
{
"make": "Toyota",
"year": "2007"
}
]
}
Once the groupingBy is used to group based on color, having issue to reduce the list (values) to oldest car by make and then collect to a map as whole.
was able to get the expected result by
Map<String, Map<String, Optional<Car>>> carMap =
carList.stream().collect(Collectors.groupingBy(Car::getColor,
Collectors.groupingBy(Car::getMake,
Collectors.minBy(Comparator.comparing(Car::getYear)))));
{red={Audi=Optional[Car(make=Audi, year=2022, color=red)], Honda=Optional[Car(make=Honda, year=1998, color=red)]}, blue={Toyota=Optional[Car(make=Toyota, year=2007, color=blue)]}}
But unable to flatmap the values in the nested map to a list of Cars in the parent map.
CodePudding user response:
Basically, you should just have to map the collected values:
cars.stream().collect(Collectors.groupingBy(Car::color,
Collectors.collectingAndThen(
Collectors.groupingBy(Car::make,
Collectors.collectingAndThen(
Collectors.minBy(Comparator.comparing(Car::year)), Optional::get)
), map -> new ArrayList<>(map.values()))));
But really, this is where streams get unreadable...
Update
To write this in at least a little more readable fashion:
Collector<Car, ?, Car> eldest = Collectors.collectingAndThen(
Collectors.minBy(Comparator.comparing(Car::year)),
Optional::get);
Collector<Car, ?, List<Car>> eldestByMake = Collectors.collectingAndThen(
Collectors.groupingBy(Car::make, eldest),
map -> new ArrayList<>(map.values()));
cars.stream().collect(Collectors.groupingBy(Car::color, eldestByMake));