我想将流中的项收集到一个映射中,该映射将相等的对象分组在一起,并映射到出现的数量。

List<String> list = Arrays.asList("Hello", "Hello", "World");
Map<String, Long> wordToFrequency = // what goes here?

所以在这种情况下,我想地图由这些条目组成:

Hello -> 2
World -> 1

我该怎么做呢?


当前回答

下面是一个对象列表的例子

Map<String, Long> requirementCountMap = requirements.stream().collect(Collectors.groupingBy(Requirement::getRequirementType, Collectors.counting()));

其他回答

我认为你只是在寻找超载,这需要另一个Collector来指定对每个组做什么……然后collections .counting()来进行计数:

import java.util.*;
import java.util.stream.*;

class Test {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();

        list.add("Hello");
        list.add("Hello");
        list.add("World");

        Map<String, Long> counted = list.stream()
            .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));

        System.out.println(counted);
    }
}

结果:

{Hello=2, World=1}

(也可以使用groupingByConcurrent来提高效率。如果在您的上下文中安全的话,那么在您的实际代码中需要记住这一点。)

List<String> list = new ArrayList<>();

list.add("Hello");
list.add("Hello");
list.add("World");

Map<String, List<String>> collect = list.stream()
                                        .collect(Collectors.groupingBy(o -> o));
collect.entrySet()
       .forEach(e -> System.out.println(e.getKey() + " - " + e.getValue().size()));

下面是StreamEx提供的简单解决方案:

StreamEx.of(list).groupingBy(Function.identity(), MoreCollectors.countingInt());

这样做的好处是减少了Java流样板代码:

下面是一个对象列表的例子

Map<String, Long> requirementCountMap = requirements.stream().collect(Collectors.groupingBy(Requirement::getRequirementType, Collectors.counting()));

这里有一些稍微不同的选项来完成手头的任务。

使用toMap:

list.stream()
    .collect(Collectors.toMap(Function.identity(), e -> 1, Math::addExact));

使用地图::合并:

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