代码之家  ›  专栏  ›  技术社区  ›  Eduardo

Java Streams:按两个字段对列表进行分组

  •  3
  • Eduardo  · 技术社区  · 7 年前

    我有一张汽车清单

    List<Car> cars = ...;

    汽车有一个 Owner 和和 物主 有一个 ContactNumber

    汽车

    public class Car {
        private Owner owner;
        public Owner getOwner(){
           return owner;
        }
    }
    

    物主

    public class Owner {
        private ContactNumber contactNumber;
        public ContactNumber getContactNumber() {
            return contactNumber;
        }
    }
    

    我知道我可以使用

    Map<Owner, List<Car>> groupByOwner = cars.stream().collect(groupingBy(Car::getOwner));
    

    是否有一种方法可以使用流进行分组 物主 联系人号码 知道那个 联系人号码 只能与一个关联 物主 ?

    如果 联系人号码 可由多个共享 物主 s

    i、 e创建以下地图:

    Map<Owner, List<Car>> groupByOwner = cars.stream().collect(groupingBy(Car::getOwner))
    Map<ContactNumber, Map<Owner, List<Car>>> groupByContactNumberAndOwner = groupByOwner...
    
    2 回复  |  直到 7 年前
        1
  •  7
  •   fps    7 年前

    如果你知道的话

    ContactNumber 只能与一个关联 Owner

    那么,就不需要内部贴图了。直接分组方式 联系人号码 :

    Map<ContactNumber, List<Car>> groupByOwnerContactNumber = cars.stream()
        .collect(Collectors.groupingBy(c -> c.getOwner().getContactNumber()));
    

    不要害怕使用lambda表达式;)


    编辑:

    根据你问题的第二部分:

    如果a 联系人号码 可由多个共享 Owners

    您可以使用的重载版本进行嵌套分组 Collectors.groupingBy 接受下游收集器的:

    Map<ContactNumber, Map<Owner, List<Car>>> groupByOwnerAndContactNumber = 
        cars.stream().collect(Collectors.groupingBy(
                c -> c.getOwner().getContactNumber(),
                Collectors.groupingBy(Car::getOwner)));
    

    另一种方法是通过复合键分组 (ContactNumber, Owner) . 您可以通过以下方式实现这一点: List<Object> :

    Map<List<Object>, List<Car>> groupByCompundOwnerContactNumber = 
        cars.stream().collect(Collectors.groupingBy(
            c -> Arrays.asList(c.getOwner().getContactNumber(), c.getOwner())));
    

    这不需要嵌套分组操作。

    注意:如果您使用的是Java 9,则可以使用 List.of 而不是 Arrays.asList .

        2
  •  3
  •   Eduardo    7 年前

    获取 Map<ContactNumber, Map<Owner, List<Car>>> 我正在寻找的收藏我必须做到:

    Map<ContactNumber, Map<Owner, List<Car>>> response = cars.stream()
                        .collect(groupingBy(c -> c.getOwner().getContactNumber(), groupingBy(Car::getOwner)));
    

    使用重载收集器

    groupingBy(Function<? super T, ? extends K> classifier, Collector<? super T, A, D> downstream)
    

    您将使用的位置:

    groupingBy(
        list element -> root key of the map, 
        groupingBy(list element -> second level key of the map)
    );