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 上找到本文的源代码。


« 上一篇: Java Weekly, 第393期
» 下一篇: 学习JUnit