提问者:小点点

如何根据特定字段流式传输和收集多个max项


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

如何将颜色作为键和值的地图流式传输和收集到具有由make创建的最旧汽车的汽车列表?最终的地图应该有

{
  "red": [
    {
      "make": "Honda",
      "year": "1998"
    },
    {
      "make": "Audi",
      "year": "2022"
    }
  ],
  "blue": [
    {
      "make": "Toyota",
      "year": "2007"
    }
  ]
}

一旦groupingBy用于基于颜色进行分组,通过make将列表(值)减少到最旧的汽车,然后收集到整个地图。

能够得到预期的结果

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={奥迪=可选[汽车(品牌=奥迪,年份=2022,颜色=红色)],本田=可选[汽车(品牌=本田,年份=1998,颜色=红色)]},蓝色={丰田=可选[汽车(品牌=丰田,年份=2007,颜色=蓝色)]}}

但无法将嵌套映射中的值平面映射到父映射中的汽车列表。


共1个答案

匿名用户

基本上,您应该只需要映射收集的值:

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

但实际上,这就是流变得不可读的地方…

更新

至少用更易读的方式来写:

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