Java Streams:按两个字段

时间:2018-02-22 17:06:37

标签: java java-stream

我有一个汽车列表

List<Car> cars = ...;

汽车有OwnerOwnerContactNumber

汽车

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

有没有办法我可以使用流分组OwnerContactNumber知道一个ContactNumber只能与一个Owner相关联?

如果多个ContactNumber可以共享Owner,我该怎么做呢?

即创建以下地图:

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

2 个答案:

答案 0 :(得分:3)

如果你知道

  

一个ContactNumber只能与一个Owner

相关联

然后,您不需要内部地图。只需直接按ContactNumber分组:

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

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

修改

根据问题的第二部分:

  

如果多个ContactNumber

可以共享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

答案 1 :(得分:1)

要获得我正在寻找的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)
);