用collectors.tomap构建主键到对象的内存索引,核心是将流中实体按唯一主键(如id)映射为map,支持o(1)查找;需确保主键非null且唯一,否则抛illegalstateexception;泛型键类型须与主键字段一致(如long/string),值类型为实体类;重复key需指定merge函数,可选定制map实现类如treemap或concurrenthashmap。

用 Collectors.toMap 构建主键到对象的内存索引,核心是把流中每个实体按唯一主键(如 id)映射为 Map<k v></k>,后续可直接 get() 查找,避免遍历。
明确主键字段与泛型类型
确保主键字段非 null 且全局唯一,否则会抛 IllegalStateException(重复 key)。泛型需匹配:键类型对应主键字段类型(如 Long、String),值类型为实体类本身。
- 若主键是
Long id,键类型用Long;若主键是String code,键类型用String - 避免用
int等基本类型——toMap要求引用类型,应写Integer - 实体类需保证主键字段在流中不重复;如有重复,需额外指定 merge 函数处理冲突
基础写法:主键提取 + 对象本身作为 value
最常见场景:用 id 做 key,原对象做 value。使用方法引用更简洁:
List<user> users = ...;
Map<long user> indexById = users.stream()
.collect(Collectors.toMap(User::getId, Function.identity()));</long></user>
其中 User::getId 提取 key,Function.identity() 表示 value 就是当前元素本身。
处理重复主键或空主键
当数据可能含重复 id 或 null 主键时,必须提供 merge 函数和 key mapper 的空值防护:
- 跳过 null 主键:
user -> user.getId() != null ? user.getId() : -1L(慎用占位符,建议提前过滤) - 保留第一个遇到的对象(丢弃后出现的):
(u1, u2) -> u1 - 合并逻辑(如取更新时间较新的):
(u1, u2) -> u1.getUpdateTime().isAfter(u2.getUpdateTime()) ? u1 : u2 - 完整示例:
Map<long user> index = list.stream()<br> .filter(u -> u.getId() != null)<br> .collect(Collectors.toMap(<br> User::getId,<br> Function.identity(),<br> (u1, u2) -> u1 // 冲突时保留前者<br> ));</long>
定制 Map 实现类(可选)
默认返回 HashMap,如需排序或并发安全,可传入 supplier:
- 按 key 排序:
TreeMap::new - 线程安全(读多写少):
ConcurrentHashMap::new - 示例:
Map<string order> indexByCode = orders.stream()<br> .collect(Collectors.toMap(<br> Order::getOrderCode,<br> Function.identity(),<br> (o1, o2) -> o1,<br> TreeMap::new<br> ));</string>










