java stream api 将集合转为 map 的核心方法是使用 collectors.tomap()。通过指定键提取函数和值提取函数,可以完成基础的映射;若遇到键冲突,必须提供合并函数来处理重复键的情况,否则程序会抛出异常。

如何处理键冲突
当集合中存在多个元素映射到同一个键时,toMap() 默认会抛出 IllegalStateException。解决此问题的标准做法是传入第三个参数,即一个 BiFunction 合并函数。该函数定义了两个值发生冲突时如何生成最终的值,例如保留旧值、保留新值或进行数值累加。

import java.util.*;
import java.util.stream.Collectors;
public class Main {
public static void main(String[] args) {
List<Person> people = Arrays.asList(
new Person("Alice", 30),
new Person("Bob", 25),
new Person("Alice", 35)
);
// 处理键冲突:保留后出现的值
Map<String, Integer> map = people.stream()
.collect(Collectors.toMap(
Person::getName,
Person::getAge,
(existing, replacement) -> replacement
));
System.out.println(map);
}
}
class Person {
private String name;
private int age;
public Person(String name, int age) { this.name = name; this.age = age; }
public String getName() { return name; }
public int getAge() { return age; }
}
如何保证返回可修改的 Map
默认的 toMap() 返回的是一个不可变(unmodifiable)的 Map。如果在后续代码中需要向这个 Map 添加或删除元素,直接操作会抛出 UnsupportedOperationException。解决方法是在收集器链的末尾追加 .collectingAndThen(),并在其中将结果转换为一个新的可变 Map 实现类,如 HashMap。
立即学习“Java免费学习笔记(深入)”;

import java.util.*;
import java.util.stream.Collectors;
public class Main {
public static void main(String[] args) {
List<Person> people = Arrays.asList(
new Person("Alice", 30),
new Person("Bob", 25)
);
// 确保返回的是可修改的 HashMap
Map<String, Integer> mutableMap = people.stream()
.collect(Collectors.collectingAndThen(
Collectors.toMap(Person::getName, Person::getAge),
HashMap::new
));
mutableMap.put("Charlie", 40); // 成功执行
System.out.println(mutableMap);
}
}
class Person {
private String name;
private int age;
public Person(String name, int age) { this.name = name; this.age = age; }
public String getName() { return name; }
public int getAge() { return age; }
}
如果输入集合为空会发生什么
当源集合为空时,toMap() 依然会正常执行并返回一个空的 Map 实例。由于没有元素参与映射,不会触发键冲突检查,也不会产生空指针异常。返回的 Map 类型取决于是否使用了 collectingAndThen,未使用时为不可变空 Map,使用时为空的 HashMap。这在处理可能为空的列表时非常安全,无需额外的判空逻辑。


















