Java中用Lambda表达式做集合交叉分析,核心是filter+contains组合,配合字段提取或自定义逻辑实现高效交集计算;基础类型直接contains,对象需重写equals/hashCode,多字段匹配应预构建Set提升性能,避免filter内重建流,并注意空指针与并发修改风险。

Java 中用 Lambda 表达式做集合交叉分析,核心是借助 Stream API 的 filter + contains 组合,配合对象字段提取或自定义判断逻辑,实现高效、可读、无副作用的交集计算。
用 stream().filter() 找出两个 List 的交集
最常用也最直观的方式:遍历一个集合,保留其中也存在于另一个集合的元素。
- 基础类型(如 String、Integer)可直接用
list2.contains(item) - 对象集合需注意:默认调用
equals()判断相等,务必确保目标类重写了equals和hashCode - 若只想按某个字段(如 id、name)匹配,应先提取字段值生成 Set,提升性能
示例(按 id 匹配):
Set<Long> oldIds = saleTaskItemOldList.stream()
.map(SaleTaskItem::getId)
.collect(Collectors.toSet());
List<SaleTaskItem> intersection = saleTaskItemNewList.stream()
.filter(item -> oldIds.contains(item.getId()))
.collect(Collectors.toList());
按多个字段或复杂条件做交叉判断
当交集逻辑不止依赖单个字段(比如“姓名相同且手机号不为空”),可在 filter 中写完整表达式。
立即学习“Java免费学习笔记(深入)”;
- 避免在 filter 内部反复调用 stream() 或 collect(),否则每次判断都重建集合,性能极差
- 推荐预先构建查找结构(如 Map 或 Set),尤其当一方数据量较大时
- 条件可链式叠加,语义清晰:.filter(u -> u.getAge() > 18).filter(u -> u.isActive())
示例(姓名+邮箱同时匹配):
Set<String> oldKeySet = saleTaskItemOldList.stream()
.map(u -> u.getName() + "|" + u.getEmail())
.collect(Collectors.toSet());
List<SaleTaskItem> matched = saleTaskItemNewList.stream()
.filter(u -> oldKeySet.contains(u.getName() + "|" + u.getEmail()))
.collect(Collectors.toList());
处理对象交集时的常见陷阱
实际开发中容易踩坑的地方,直接影响结果正确性:
- Arrays.asList() 返回的 List 不支持 add/remove:若后续要修改交集结果,先 new ArrayList(result)
- 未重写 equals/hashCode 导致对象交集为空:哪怕字段值完全一样,也会被当成不同对象
- 并发修改异常(ConcurrentModificationException):不要在 filter 或 map 中修改正在遍历的原集合
- 空指针风险:字段可能为 null,建议用 Objects.equals(a, b) 替代 a.equals(b)
扩展:交集之外的关联分析(差集、并集)
交叉分析常伴随对比需求,Lambda 同样简洁支持:
-
差集(A − B):A 中存在但 B 中不存在的元素 →
A.stream().filter(item -> !B.contains(item)) -
并集(A ∪ B):合并后去重 →
Stream.concat(A.stream(), B.stream()).distinct().collect(...) - 对称差集(A ⊕ B):只在 A 或只在 B 的元素 → 先算 A−B 和 B−A,再合并
所有操作均返回新集合,原始 List 完全不受影响,适合函数式、不可变风格的数据处理。


















