Java GroupingBy:一款强大的集合分组工具

发布时间:2023-05-20

一、GroupingBy介绍

Java GroupingBy是一款用于集合分组的工具,属于Java8 Stream API提供的工具之一。它可以方便地对集合中的元素进行分组,生成Map<key, list<value>>类型的结果,其中Key是String、Integer等类型,而Value则是集合中的元素类型。GroupingBy的主要作用是将集合中的元素按照指定的规则进行分组,为我们提供了一个简便的选择,可以避免我们手动编写Java代码来完成此操作。

二、GroupingBy使用方法

使用Java GroupingBy可以简单地将集合中的元素按照指定的规则进行分组。我们可以使用实例代码来演示GroupingBy的使用方法:

List<Person> persons = new ArrayList<>();
persons.add(new Person("John", "Smith", 25));
persons.add(new Person("Jane", "Doe", 20));
persons.add(new Person("John", "Doe", 30));
Map<String, List<Person>> grouped = persons.stream().collect(Collectors.groupingBy(Person::getFirstName));
grouped.forEach((key, value) -> System.out.println(key + ": " + value));

在上述例子中,我们首先定义了一个包含3个Person对象的List集合,然后使用GroupingBy将Person按照firstName进行分组,生成了一个Map<String, List<Person>>类型的结果。最后输出分组后的结果,可以看到结果如下:

John: [Person{firstName='John', lastName='Smith', age=25}, Person{firstName='John', lastName='Doe', age=30}]
Jane: [Person{firstName='Jane', lastName='Doe', age=20}]

三、GroupingBy常用方法

1. groupingBy(Function<T, K> classifier)

这是GroupingBy的最基本方法,在分组时,根据T类型的元素执行Function函数,返回一个K类型的键值,最终生成以K类型为键,以List<T>类型为值的Map对象。 以下是一个例子:

List<String> list = Arrays.asList("Hello", "World", "Java", "Stream", "API");
Map<Character, List<String>> result = list.stream().collect(Collectors.groupingBy(str -> str.charAt(0)));
result.forEach((key, value) -> System.out.println(key + "-->" + value));

代码执行结果如下:

A-->[API]
H-->[Hello]
J-->[Java, Stream]
W-->[World]

2. groupingBy(Function<T, K> classifier, Collector<T, ?, U> downstream)

groupingBy(Function<T, K> classifier)函数类似,不同的是该函数可提供一个downstream收集器参数。downstream收集器用于对元素集合进行进一步操作。我们可以用它来分组元素,并对每个组进行进一步的计算。下面是一个例子:

Map<Character, Integer> result = list.stream()
        .collect(Collectors.groupingBy(str -> str.charAt(0), Collectors.summingInt(value -> value.length())));
result.forEach((key, value) -> System.out.println(key + "-->" + value));

代码执行结果如下:

A-->3
H-->5
J-->8
W-->5

3. groupingBy(Function<T, K> classifier, Supplier<Map<K, D>> mapFactory, Collector<T, A, D> downstream)

该函数与前述函数相似,差别在于它提供了一个mapFactory,可以自定义Map<K,D>类型存储参数、结果类型。我们可以用它来自定义生成Map对象,在某些情况下很有用。下面是一个例子:

Map<Character, Map<String, List<String>>> result = list.stream().collect(Collectors.groupingBy(str -> str.charAt(0), TreeMap::new,
        Collectors.groupingBy(str -> String.valueOf(str.length()))));
result.forEach((k1, v1) -> {
    System.out.println(k1 + ":");
    v1.forEach((k2, v2) -> System.out.println("--" + k2 + "--:" + v2));
});

代码执行结果如下:

A:
--3--:[API]
H:
--5--:[Hello]
J:
--4--:[Java]
--6--:[Stream]
W:
--5--:[World]

四、GroupingBy的局限性

虽然GroupingBy这款工具是强大的,但它也有一些局限性。首先,在组合时,必须要选择某个元素进行分组。此外,GroupingBy只适用于List类型的集合,如果是Set等其他集合类型,需要先转换为List类型。此外,由于Java程序在运行时的限制,GroupingBy中的键类型只能是String、Integer等基本类型,而无法使用更复杂的类型。

五、总结

总之,Java GroupingBy是一种非常有用的集合分组工具,可以让我们在处理集合时更加方便,总结起来有以下几个特点:

  1. GroupingBy可以将集合中的元素按照指定的规则进行分组;
  2. GroupingBy可以生成Map<Key, List<Value>>类型的结果;
  3. GroupingBy可以方便地处理集合,避免了手动编写Java代码的繁琐操作。