如何移除ArrayList中的元素?自定义对象移除失败的解决方案
解决ArrayList移除自定义对象失败的问题
你的代码里调用remove(new A(5))后元素没被移除,核心问题出在自定义类A没有重写equals()和hashCode()方法,下面我来拆解原因和解决方案:
为什么移除失败?
当ArrayList执行remove(Object o)时,会遍历集合中的元素,用传入的对象o和集合里的每个元素调用equals()方法比较。默认情况下,所有类继承自Object的equals()方法是比较对象的内存地址——你新new出来的A(5)和之前添加到集合里的A(5)是两个完全不同的对象(内存地址不一样),所以ArrayList找不到匹配的元素,自然不会执行移除操作。
另外还要提一句:你的原代码里类B的逻辑直接写在类体里是编译错误的,必须放在方法(比如main方法)里才能运行,这个小问题也得修正。
解决方案1:重写equals()和hashCode()
要让ArrayList能识别“value相同的A对象是相等的”,就需要给类A重写这两个方法,基于value字段来判断对象相等性:
import java.util.Objects; class A { int value; public A(int newValue) { setValue(newValue); } public int getValue() { return value; } public void setValue(int newValue) { value = newValue; } @Override public boolean equals(Object o) { // 先判断是否是同一个对象引用,是的话直接返回相等 if (this == o) return true; // 如果传入的是null或者类型不同,直接不相等 if (o == null || getClass() != o.getClass()) return false; // 强转为A类型,比较value字段 A a = (A) o; return value == a.value; } @Override public int hashCode() { // 用Objects.hash生成基于value的哈希值,和equals保持逻辑一致 return Objects.hash(value); } }
然后修正类B的代码,把逻辑放到main方法里,同时优化打印逻辑(原代码打印value会输出对象地址,改成getValue()更直观):
import java.util.ArrayList; class B { public static void main(String[] args) { ArrayList<A> valuesOfA = new ArrayList<>(); valuesOfA.add(new A(5)); System.out.println("Adding..."); for (A value : valuesOfA) { System.out.println(value.getValue()); } valuesOfA.remove(new A(5)); System.out.println("Removed"); for (A value : valuesOfA) { System.out.println(value.getValue()); } } }
现在运行代码,就能成功移除元素了。
解决方案2:手动遍历找到目标元素再移除
如果你不想重写equals()和hashCode(),也可以手动遍历集合,找到匹配的元素后移除。这里要注意:不要用增强for循环遍历并移除,会抛出ConcurrentModificationException,建议用迭代器或者普通for循环(从后往前遍历):
用迭代器的方式(推荐,线程安全)
import java.util.ArrayList; import java.util.Iterator; class B { public static void main(String[] args) { ArrayList<A> valuesOfA = new ArrayList<>(); valuesOfA.add(new A(5)); System.out.println("Adding..."); for (A value : valuesOfA) { System.out.println(value.getValue()); } // 用迭代器遍历并移除 Iterator<A> iterator = valuesOfA.iterator(); while (iterator.hasNext()) { A a = iterator.next(); if (a.getValue() == 5) { iterator.remove(); // 用迭代器的remove方法,避免并发修改异常 } } System.out.println("Removed"); for (A value : valuesOfA) { System.out.println(value.getValue()); } } }
普通for循环(从后往前遍历)
// 遍历集合,从最后一个元素开始往前找 for (int i = valuesOfA.size() - 1; i >= 0; i--) { A a = valuesOfA.get(i); if (a.getValue() == 5) { valuesOfA.remove(i); } }
这样也能成功移除目标元素,不需要修改类A的代码。
内容的提问来源于stack exchange,提问作者Sampreeth Amith
相关产品推荐
相关产品推荐

