对比同类型对象ArrayList并移除共同元素的实现问题
移除ArrayList中存在于另一个ArrayList的元素
首先,如果你已经写了部分正向遍历的for循环,大概率会碰到索引错位的坑——删除元素后后面的元素会往前移,导致漏删或者数组越界。下面给你几种实用的解决方案,从简洁到高效都有:
方法1:用自带方法一步搞定(最省心)
Java的ArrayList原生就提供了removeAll()方法,完全匹配你的需求:移除所有在指定集合中存在的元素。代码超简单:
arrayListA.removeAll(arrayListB);
⚠️ 注意:你的自定义对象必须正确重写equals()(最好连带hashCode()一起),否则默认会用对象内存地址比较,可能达不到预期效果。比如自定义类可以这么写:
public class YourObject { private String uniqueId; // 其他字段、构造方法 @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; YourObject that = (YourObject) o; return Objects.equals(uniqueId, that.uniqueId); // 用唯一标识或关键字段判断相等 } @Override public int hashCode() { return Objects.hash(uniqueId); } }
方法2:手动循环的正确写法(避免索引坑)
如果想自己实现循环逻辑,一定要倒序遍历,这样删除元素后不会影响前面未遍历的元素索引:
// 从最后一个元素往回遍历 for (int i = arrayListA.size() - 1; i >= 0; i--) { YourObject currentObj = arrayListA.get(i); if (arrayListB.contains(currentObj)) { arrayListA.remove(i); } }
为什么不能正向遍历?举个例子:正向遍历到索引2的元素并删除,原来索引3的元素会移到索引2的位置,下一次循环i变成3,就会跳过这个元素,导致漏删。倒序遍历就不会有这个问题~
方法3:大数据量优化版(性能拉满)
如果你的ArrayList元素很多,上面两种方法的时间复杂度是O(n*m)(因为contains()是O(m))。可以先把B转成HashSet,让contains()的时间复杂度降到O(1),整体变成O(n):
Set<YourObject> bSet = new HashSet<>(arrayListB); // 用倒序循环或者直接调用removeAll都可以 arrayListA.removeAll(bSet);
这种处理方式在数据量大的时候性能提升非常明显。
内容的提问来源于stack exchange,提问作者Rektirino
相关产品推荐
相关产品推荐

