Java流-使用GroupingBy和计数收集到地图,但是如果特定字段为空,则计数为0

Mel*_*lih 5 java lambda functional-programming java-stream java-11

为了保护这个问题免受“重复猎人”的侵扰,我需要提及的是,我并不认为我正在寻找的解决方案是过滤。我进行了搜索,从未遇到提及过滤的答案。

我有一个像这样的类的对象列表:

class Person {
  String gender;
  String income;
  String petName;
}
Run Code Online (Sandbox Code Playgroud)

我想将此列表收集到地图中,按性别分组,并计算它们拥有的宠物,如果petName为null,则当然需要传递0。

Map<String, Long> mapping = people
  .stream()
  .collect(Collectors.groupingBy(Person::gender, Collectors.counting());
Run Code Online (Sandbox Code Playgroud)

不实现Collector接口及其5种方法(因为我已经在尝试摆脱另一个自定义收集器),如果它的petName字段是,如何使它不计入对象null

我可以从Java-11中受益

Rav*_*ala 8

首先,将所有人员按性别分组,然后使用过滤器收集器过滤掉具有空名称的人员。最后,使用下游计数收集器来计数属于每个类别的元素的数量。这是它的外观。

Map<String, Long> peopleCntByGender = people.stream()
    .collect(Collectors.groupingBy(Person::getGender, 
        Collectors.filtering(p -> p.getPetName() != null, 
            Collectors.counting())));
Run Code Online (Sandbox Code Playgroud)

但是,过滤收集器仅在Java9中可用,因此,如果您使用的是Java8,并且无法轻松迁移到Java9,请考虑编写自己的自定义filtering收集器并在此处使用。此答案或JDK 9源代码可能会有所帮助。

  • 有关使用Java-8的实现,请参考[如何在java流中对groupBy应用过滤](/sf/ask/3379116331/ ) (6认同)
  • 只需调用一下,`Collectors.filtering`就可以与Java-9及更高版本一起使用。 (4认同)