1. 概述
在这个简短的教程中,我们将了解如何在 Java 中对相等的对象进行分组并计算它们的出现次数。我们将使用 Java 中的 groupingBy() 收集器。
2. 使用 Collectors.groupingBy() 计算出现次数
Collectors.groupingBy() 提供类似于 SQL 中的 GROUP BY 子句的功能。 我们可以使用它按任何属性对对象进行分组并将结果存储在 Map 中。
例如,让我们考虑一个场景,我们需要将流中相等的 String 分组并计算它们的出现次数:
List<String> list = new ArrayList<>(Arrays.asList("Foo", "Bar", "Bar", "Bar", "Foo"));
我们可以将相等的字符串分组,在本例中为“Foo”和“Bar”。结果 Map 会将这些字符串存储为键。这些键的值将是出现次数。 “Foo”的值为 2,“Bar”的值为 3:
Map<String, Long> result = list.stream()
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
Assert.assertEquals(new Long(2), result.get("Foo"));
Assert.assertEquals(new Long(3), result.get("Bar"));
我们来解码一下上面的代码片段:
- Map<String, Long> 结果 – 这是输出结果 Map ,它将把分组的元素存储为键,并将它们的出现次数作为值进行计数
- list.stream() – 我们 将列表元素转换为Java 流,以声明的方式处理集合
- Collectors.groupingBy() – 这是 Collectors 类的方法,用于按某些属性对对象进行分组并将结果存储在 Map 实例中
- Function.identity()—— 它是Java中的函数式接口; 身份 方法返回一个始终返回其输入参数的 函数
- Collectors.counting() – 此 Collectors 类方法计算流中作为参数传递的元素数量
我们可以使用 Collectors.groupingByConcurrent() 而不是 Collectors.groupingBy()。 它还对输入流元素执行分组操作。该方法将结果收集到 ConcurrentMap 中,从而提高效率。
例如,对于输入列表:
List<String> list = new ArrayList<>(Arrays.asList("Adam", "Bill", "Jack", "Joe", "Ian"));
我们可以使用 Collectors.groupingByConcurrent() 对 相等长度的字符串进行分组:
Map<Integer, Long> result = list.stream()
.collect(Collectors.groupingByConcurrent(String::length, Collectors.counting()));
Assert.assertEquals(new Long(2), result.get(3));
Assert.assertEquals(new Long(3), result.get(4));
三、结论
在本文中,我们介绍了如何使用 Collector.groupingBy() 对相等的对象进行分组。
最后,您可以在 GitHub 上找到本文的源代码。