Java Stream API:分组与分区的艺术
在Java 8中引入的Stream API彻底改变了我们处理集合的方式。其中,groupingBy是一个功能强大的操作,它允许我们轻松地对数据进行分组和分区。本文将深入探讨groupingBy的用法,并通过实际示例展示其强大的功能。

分组的基本概念
groupingBy是Collectors类中的一个静态方法,主要用于将流中的元素按照某个属性进行分组。其基本语法如下:
Map<K, List<T>> groupedMap = stream.collect(Collectors.groupingBy(Function<? super T, ? extends K> classifier));
这里的classifier是一个函数,用于确定每个元素应分到哪个组。
简单示例
假设我们有一个Person类,包含姓名和年龄属性。我们希望按年龄分组:
class Person {
String name;
int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public int getAge() {
return age;
}
}
List<Person> people = Arrays.asList(
new Person("Alice", 30),
new Person("Bob", 30),
new Person("Charlie", 25)
);
Map<Integer, List<Person>> groupedByAge = people.stream()
.collect(Collectors.groupingBy(Person::getAge));
System.out.println(groupedByAge);
输出将是:
{30=[Alice, Bob], 25=[Charlie]}
分组的进阶用法
多级分组
groupingBy还可以进行多级分组。例如,我们不仅按年龄分组,还希望在每组内按姓名的首字母分组:
Map<Integer, Map<Character, List<Person>>> multiGrouped = people.stream()
.collect(Collectors.groupingBy(
Person::getAge,
Collectors.groupingBy(p -> p.name.charAt(0))
));
System.out.println(multiGrouped);
输出将是:
{30={A=[Alice], B=[Bob]}, 25={C=[Charlie]}}
分组与聚合
除了简单的分组,我们还可以在分组的同时进行聚合操作。例如,计算每个年龄组的人数:
Map<Integer, Long> ageCount = people.stream()
.collect(Collectors.groupingBy(
Person::getAge,
Collectors.counting()
));
System.out.println(ageCount);
输出将是:
{30=2, 25=1}
分区的基本概念
分区是分组的一种特殊形式,它将元素分为两个组:满足条件的和不满足条件的。使用partitioningBy可以实现这一功能:
Map<Boolean, List<T>> partitionedMap = stream.collect(Collectors.partitioningBy(Predicate<? super T> predicate));
简单示例
假设我们希望将人员分为年龄大于30和小于等于30的两个组:
Map<Boolean, List<Person>> partitionedByAge = people.stream()
.collect(Collectors.partitioningBy(p -> p.getAge() > 30));
System.out.println(partitionedByAge);
输出将是:
{false=[Alice, Bob, Charlie], true=[]}
分区与聚合
与分组类似,分区也可以结合聚合操作。例如,计算年龄大于30和小于等于30的人员数量:
Map<Boolean, Long> agePartitionCount = people.stream()
.collect(Collectors.partitioningBy(
p -> p.getAge() > 30,
Collectors.counting()
));
System.out.println(agePartitionCount);
输出将是:
{false=3, true=0}
总结
groupingBy和partitioningBy是Java Stream API中非常实用的工具,它们极大地简化了数据的分组和分区操作。通过结合多级分组和聚合操作,我们可以轻松实现复杂的数据处理需求。希望本文的示例能帮助你更好地理解和应用这些强大的功能。在未来的开发中,不妨多尝试使用这些方法,让你的代码更加简洁高效。