【问题标题】:Java Streams - Collecting to a Map With GroupingBy and Counting, But Count 0 If A Specific Field Is Null [duplicate]Java Streams-使用GroupingBy和计数收集到地图,但如果特定字段为空,则计数为0 [重复]
【发布时间】:2020-02-06 16:16:36
【问题描述】:

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

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

class Person {
  String gender;
  String income;
  String petName;
}

我想把这个List收集成一个map,按性别分组,统计他们拥有的宠物,当然如果petName为null的话需要传0。

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

没有实现 Collector 接口和它的 5 个方法(因为我已经在尝试摆脱另一个自定义收集器)如果它的 petName 字段是 null,我怎样才能使它不计算对象。

我可以从 Java-11 中受益

【问题讨论】:

标签: java lambda functional-programming java-stream java-11


【解决方案1】:

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

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

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

【讨论】:

  • 请注意,Collectors.filtering 适用于 Java-9 及更高版本。
  • 有趣,我确实使用 Java9,所以在这种情况下,OP 需要为 Java8 编写一个。
  • 有关 Java-8 的实现,请参阅 How to apply Filtering on groupBy in java streams
  • 我们使用的是 Java-11,没有问题。与其建议新的依赖或升级,不如为 Java-8 提供解决方案
【解决方案2】:

关于上面的评论(关于在性别没有宠物的情况下需要0)我相信以下内容可以满足您的要求:

people.stream()
      .collect(Collectors.toMap(Person::getGender,
                person -> person.getPetName() == null ? 0L : 1L,
                Long::sum));

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-09-04
    • 2019-09-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多