Java实现distinctByKey时putIfAbsent返回值为何与null比较?
核心Lambda表达式含义与判断逻辑说明
一、这行Lambda的具体执行逻辑
这行代码是distinctByKey方法返回的**流过滤断言(Predicate)**的核心实现,每个经过当前filter操作的流元素都会执行这段逻辑,逐步骤拆解如下:
- 对当前遍历到的流元素
t,调用传入的keyExtractor函数提取用来去重的属性值:比如传入方法引用XYZ::getName时,这一步就是取当前XYZ对象的name属性作为去重键;传入XYZ::getPrice时就是取price作为去重键。 - 调用当前去重规则专属的
seen(ConcurrentHashMap实例)的putIfAbsent方法,尝试把提取到的去重键存入map,固定存入的value是Boolean.TRUE——这个map本质就是个标记集合,只用来记录哪些去重键已经出现过,value本身没有实际业务含义。 - 最后把
putIfAbsent的返回值和null做相等判断,得到的布尔值就是当前断言的返回结果,直接决定当前元素是被保留还是被过滤。
二、为何要将putIfAbsent返回值与null比较作为过滤条件
要理解这个判断的设计逻辑,首先得明确ConcurrentHashMap.putIfAbsent(K key, V value)方法的固定返回规则:
如果传入的key在map中不存在:方法会将传入的key-value对写入map,返回值为
null;
如果传入的key在map中已经存在:方法不会执行任何写入操作,直接返回这个key之前绑定的旧value值。
而Stream的filter()方法的执行规则是:传入的断言返回true时当前元素会被保留进入下一个流操作,返回false时当前元素会被直接过滤丢弃。
两者结合刚好完美匹配去重的判断需求:
- 当
putIfAbsent返回null:说明当前去重键是第一次出现,不属于重复元素,判断结果为true,元素被保留,同时这个键已经被存入map,后续出现相同键的元素时就会被识别为重复项。 - 当
putIfAbsent返回非null值(也就是之前存入的Boolean.TRUE):说明当前去重键之前已经出现过,当前元素是重复项,判断结果为false,元素被过滤。
顺带说一句,这里选ConcurrentHashMap而不是普通HashMap,核心原因是putIfAbsent本身是原子操作,哪怕Stream开启并行执行模式,也不会出现多个线程同时判定同一个key为首次出现的并发问题,不管是串行流还是并行流,这套去重逻辑都能正常生效。
内容的提问来源于stack exchange,提问作者Darkwriter
相关产品推荐
相关产品推荐

