0
 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.

Jan Jaff
  • 5
  • 2
  • Please edit your question to show a minimal runnable example which illustrates your problem. You say "Once the groupingBy is used to group based on color, having issue to reduce the list" but you havent shown the code you are asking about. – tgdavies Sep 28 '22 at 22:37
  • Does this answer your question? [How to group a set of objects into sorted lists using java 8?](https://stackoverflow.com/questions/32171283/how-to-group-a-set-of-objects-into-sorted-lists-using-java-8) or also [Java 8, Lambda: Sorting within grouped Lists and merging all groups to a list](https://stackoverflow.com/questions/47679265/java-8-lambda-sorting-within-grouped-lists-and-merging-all-groups-to-a-list) – knittl Sep 28 '22 at 23:23
  • @tgdavies updated the problem. – Jan Jaff Sep 28 '22 at 23:42

1 Answers1

1

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));
Mihe
  • 2,270
  • 2
  • 4
  • 14
  • I just tried running this. It doesn't produce the intended result. It produces a structure that has `Car` objects at the leaves rather than maps. That is, `Map>` rather than `Map>>` – CryptoFool Sep 29 '22 at 01:33
  • I've updated my answer to return a `Map>`. – Mihe Sep 29 '22 at 01:42
  • @CryptoFool, there was no requirement to return a `Map>>`. – Mihe Sep 29 '22 at 01:45
  • 1
    I was reading the desired result in the question as being fairly literal...that `[` and `]` represent a List, and `{` and `}` represent a Map. But perhaps the OP didn't intend that it be taken so literally. The text of the question certainly doesn't confirm this interpretation. And I see now that the OP accepted your answer, so that seals it. So I flipped my vote! – CryptoFool Sep 29 '22 at 02:00
  • Thanks, I could have been wrong, too, but the last sentence of the OPs question made me think he wants a list of Cars :-) – Mihe Sep 29 '22 at 02:18