如何使用Java流查找不同对象的数量

时间:2018-12-09 02:18:37

标签: java count java-stream distinct

我有Thing对象的列表:

Error

class Thing { public String id; public String name; } 包含以下内容;

List<Thing> lst

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

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

我该如何实现?

2 个答案:

答案 0 :(得分:3)

您可以使用Collectors.groupingByid属性,然后counting,将其出现为:

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

答案 1 :(得分:0)

一个人也可以使用toMap收集器:

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

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

或Map :: merge:

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

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

如果顺序与帖子中显示的顺序有关,则可以使用HashMap代替上面的LinkedHashMap

您还可以通过以下方式提供一个映射,在其中将元素累积到其中以保持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()));