【问题标题】:How to find counts of distinct objects using Java streams [duplicate]如何使用 Java 流查找不同对象的计数 [重复]
【发布时间】:2019-05-10 08:37:26
【问题描述】:

我有一个 Thing 对象列表:

class Thing {
    public String id;
    public String name;
}

List<Thing> lst 包含以下内容;

[{'1', 'AB'},{'2', 'CD'},{'1', 'AB'},{'1','AB'},{'2','CD'},{'3','EF'}]

现在我想使用 Java 流或任何 util 函数来获得不同的 id 计数: 我希望输出是,

id   count
1    3
2    2 
3    1

我怎样才能做到这一点?

【问题讨论】:

    标签: java count java-stream distinct


    【解决方案1】:

    也可以使用toMap 收集器:

    lst.stream().collect(toMap(Thing::getId, v -> 1, Math::addExact));
    

    创建一个Map<String, Integer>,其中Thing::getId 是用于选择映射键的键映射器,v -> 1 是用于选择映射值的值映射器,在键冲突的情况下,我们添加相应的值使用合并函数Math::addExact

    或地图::合并:

    Map<String, Integer> accumulator = new HashMap<>();
    lst.forEach(t -> accumulator.merge(t.getId(), 1, Math::addExact));
    

    与上面的想法相同,如果Thing::getId 已经存在于accumulator 映射中,我们将它们与Math::addExact 合并,否则我们将提供的键和值累积到映射中。

    如果您的帖子中显示的顺序很重要,那么您可以使用LinkedHashMap 而不是上面的HashMap

    您还可以提供一个映射,将元素累积到其中以保持toMap 收集器中的顺序:

    lst.stream().collect(toMap(Thing::getId, v -> 1, Math::addExact, LinkedHashMap::new));
    

    或使用groupingBy 收集器:

    lst.stream()
       .collect(Collectors.groupingBy(Thing::getId, 
                    LinkedHashMap::new,
                    Collectors.counting()));
    

    【讨论】:

      【解决方案2】:

      您可以使用Collectors.groupingBy id 属性然后counting 它的出现为:

      List<Thing> objects = new ArrayList<>(); // initalise as in the question 
      Map<String, Long> countForId = objects.stream()
              .collect(Collectors.groupingBy(Thing::getId, Collectors.counting()));
      

      【讨论】:

      • 我读过对于相对较小的结构,一个简单的 for 循环可以比使用流更快。也许这是需要考虑的事情,通常是spraching。
      • @Adrian,在实时场景中,我会有很多行,这就是我想要流的原因
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-05-01
      • 1970-01-01
      • 2020-03-27
      • 1970-01-01
      • 1970-01-01
      • 2021-01-14
      相关资源
      最近更新 更多