使用removeAll求列表差集时删除内容不符合预期的问题
问题原因与解决办法
为啥结果不符合预期?
先看你的数字示例:按代码逻辑,all.removeAll(common)应该得到[4,5,6,7],但实际场景里拿到[6,7],核心问题出在业务对象的equals方法实现错误——你场景中对应数字4、5的对象,被错误判定为属于common集合,调用removeAll时被一并删除了。
另外你对removeAll的行为可能有误解:这个方法会移除集合里所有和目标集合元素匹配(通过equals判断)的元素,不是只移除与目标集合元素数量对应的次数,哪怕原集合里有多个重复的匹配元素,都会被一次性清掉。
还有,你当前的方法逻辑本身就不适合求两个列表的对称差集(仅在一个列表中出现的元素),一旦列表存在重复元素,结果会完全偏离预期。
正确实现方式
如果你的业务对象有唯一标识(比如id),推荐基于唯一标识计算,完全避开equals方法的坑:
// 假设你的业务对象结构如下 class BizObj { Long id // 其他业务属性 } def listA = [new BizObj(id:1), new BizObj(id:2), new BizObj(id:3), new BizObj(id:4), new BizObj(id:5)] def listB = [new BizObj(id:1), new BizObj(id:2), new BizObj(id:3), new BizObj(id:6), new BizObj(id:7)] // 提取两边对象的唯一标识集合 def idsA = listA*.id as Set def idsB = listB*.id as Set // 筛选仅在A中存在的对象 def onlyA = listA.findAll { !idsB.contains(it.id) } // 筛选仅在B中存在的对象 def onlyB = listB.findAll { !idsA.contains(it.id) } // 合并得到最终差异结果 def diff = onlyA + onlyB
如果一定要用集合操作,必须先确保业务对象的equals和hashCode方法正确实现(能准确判断两个对象是否为同一实体),再用简洁方式计算:
def common = listA.intersect(listB) def diff = (listA + listB) - common
内容的提问来源于stack exchange,提问作者RecruitsNeededSire
相关产品推荐
相关产品推荐

