Collectors.toMap构建反向索引的核心是用对象属性作key、对象本身作value:需指定keyMapper(如User::getId)、valueMapper(Function.identity())、mergeFunction(如(u1,u2)->u1)及可选mapSupplier(如LinkedHashMap::new),并确保key唯一、规避null。
用
构建属性到对象的反向索引,核心是把对象的某个字段(如 ID、名称)作为 key,对象自身作为 value,一行流式操作就能生成
,避免手动遍历和 put。
明确 key 和 value 的来源
反向索引本质是“用属性查对象”,所以 key 必须是对象中可唯一标识它的字段(如
、
),value 通常是对象本身。例如:
key:
(Long 类型)
value:
(User 对象)
确保 key 具有唯一性,否则会抛出
(重复 key)。
基础写法:处理无重复 key 场景
最简形式直接使用方法引用:
其中
是 key mapper,
表示 value 就是当前元素本身。这是最常用、最清晰的写法。
处理重复 key:指定合并策略
当 key 可能重复(如多个用户共用同一部门编码),需传入第三个参数——merge function:
保留第一个:
保留最后一个:
合并逻辑(如取更新时间更晚的):
完整示例:
指定 Map 实现类与 null 安全
默认返回
,如需有序或线程安全,可用四参数重载:
按插入顺序:传
按 key 排序:传
key 或 value 为 null?提前过滤或映射,
不接受 null key/value
示例(保持插入顺序):
不复杂但容易忽略细节:key 唯一性、null 处理、合并逻辑选择 —— 把握这三点,
就是构建反向索引最轻量高效的方式。
Collectors.toMapMapidcodeuser.getId()userIllegalStateExceptionMap idToUser = users.stream()
.collect(Collectors.toMap(User::getId, Function.identity())); User::getIdFunction.identity()(a, b) -> a(a, b) -> b(u1, u2) -> u1.getUpdatedAt().isAfter(u2.getUpdatedAt()) ? u1 : u2Map codeToUser = users.stream()
.collect(Collectors.toMap(
User::getCode,
Function.identity(),
(u1, u2) -> u1.getCreatedAt().isBefore(u2.getCreatedAt()) ? u2 : u1 // 保留创建更新的
)); HashMapLinkedHashMap::newTreeMap::newtoMapMap orderedMap = users.stream()
.filter(Objects::nonNull)
.filter(u -> u.getId() != null)
.collect(Collectors.toMap(
User::getId,
Function.identity(),
(u1, u2) -> u1,
LinkedHashMap::new
)); toMap