背景
今天在处理一个数据分组问题是,突然想到是使用 toMap
呢还是使用 groupBy
呢,因为这两个 API 都是比较常用的,一时语塞,后来想想还是比较好区分的,下面就介绍下这两个常用的 API。
Java 8 引入了 Stream API,它为处理集合数据提供了一个声明性的方法。Stream API 提供了一系列操作来对数据进行转换和聚合,其中
toMap
和groupingBy
是两个常用的终端操作(terminal operation)。
1. toMap
操作
toMap
是 Stream 的一个收集器(collector),它将流中的元素转换为一个 Map
。该方法常用于需要将流中的数据转换为键值对的场景。
用法示例:
java
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class ToMapExample {
public static void main(String[] args) {
List<Student> students = Arrays.asList(
new Student(1, "Alice"),
new Student(2, "Bob"),
new Student(3, "Charlie")
);
Map<Integer, String> studentMap = students.stream()
.collect(Collectors.toMap(Student::getId, Student::getName));
System.out.println(studentMap);
}
}
@Data
class Student {
private int id;
private String name;
public Student(int id, String name) {
this.id = id;
this.name = name;
}
}
在这个示例中,我们将学生列表转换为一个以学生 ID 为键,学生名字为值的 Map
。
注意事项:
-
toMap
要求键是唯一的,如果流中存在重复键,会抛出IllegalStateException
。 -
可以传递第三个参数来解决键冲突:
java
.collect(Collectors.toMap(Student::getId, Student::getName, (name1, name2) -> name1));
(name1, name2) -> name1)
表示键冲突时,保留前一个数据,类似的,可以保留后面的数据。
2. groupingBy
操作
groupingBy
是另一个收集器,它基于某个分类函数对流中的元素进行分组,返回一个 Map
,键为分类依据,值为该分类下的元素列表。
用法示例:
java
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class GroupingByExample {
public static void main(String[] args) {
List<Student> students = Arrays.asList(
new Student(1, "Alice", "A"),
new Student(2, "Bob", "B"),
new Student(3, "Charlie", "A")
);
Map<String, List<Student>> studentGroups = students.stream()
.collect(Collectors.groupingBy(Student::getGrade));
System.out.println(studentGroups);
}
}
@Data
class Student {
private int id;
private String name;
private String grade;
public Student(int id, String name, String grade) {
this.id = id;
this.name = name;
this.grade = grade;
}
}
在这个示例中,我们根据学生的年级对学生进行分组,生成一个以年级为键,学生列表为值的 Map
。
注意事项:
groupingBy
的键可以是任何类型,且键不需要唯一。- 可以通过
Collectors.mapping
等进一步进行嵌套收集。
异同
相同点:
- 都是
Collectors
提供的静态方法。 - 都是终端操作,用于将流中的数据收集到
Map
中。
不同点:
- 目的不同 :
toMap
用于将流中的数据转换为键值对,而groupingBy
用于根据某个分类标准对数据进行分组。 - 返回结果 :
toMap
返回的是一个单层的Map
,键为唯一值;groupingBy
返回的是一个嵌套的Map
,键为分类标准,值为该分类下的元素列表。 - 键的唯一性 :
toMap
要求键唯一,若不唯一则需要处理冲突;groupingBy
不要求键唯一,因为每个键对应的是一个元素列表。
总结
返回的是一个嵌套的
Map`,键为分类标准,值为该分类下的元素列表。
- 键的唯一性 :
toMap
要求键唯一,若不唯一则需要处理冲突;groupingBy
不要求键唯一,因为每个键对应的是一个元素列表。
总结
toMap
和 groupingBy
是 Java Stream API 中强大的收集器,它们在数据转换和分组处理中有着广泛的应用。toMap
适用于需要将流中的数据映射为键值对的情况,而 groupingBy
则适用于需要对数据进行分类和分组的情况。理解它们的使用方法和区别,有助于更高效地处理集合数据。