Java 整数列表调用 remove(2),删掉了第三项而不是数值 2
整数参数会匹配按索引删除的重载。使用 Integer.valueOf 明确按值删除,并区分首次匹配、全部重复项和目标不存在的情况。
列表是 [2, 3, 5, 7],执行 list.remove(2) 后变成 [2, 3, 7]。如果列表不足三项,同一调用还可能抛出 IndexOutOfBoundsException。
原因是 ArrayList 有两个不同的删除重载:remove(int index) 按位置删除,remove(Object o) 按值删除。整数字面量 2 会匹配前者;声明了 ArrayList<Integer> 并不会把这个参数自动解释成元素值。
下面针对可修改的 ArrayList<Integer>,使用 Java 8 及以上可用的写法。固定大小或不可修改列表还可能有独立的删除限制,应另行处理。
明确传入 Integer 对象
import java.util.ArrayList;
import java.util.Arrays;
public class Main {
public static void main(String[] args) {
ArrayList<Integer> values = new ArrayList<Integer>(
Arrays.asList(2, 3, 5, 7)
);
boolean removed = values.remove(Integer.valueOf(2));
System.out.println(removed); // 预期 true
System.out.println(values); // 预期 [3, 5, 7]
}
}
Integer.valueOf(2) 让这次调用匹配按对象删除的重载。它只删除第一个相等元素,并返回是否实际删除;不存在该值时返回 false,列表保持原样。
排查时先看参数的声明类型。例如 int target = 2 再调用 remove(target) 仍然按索引;按值删除时保持 remove(Integer.valueOf(target)),意图更清楚。没有必要使用整数对象构造器,也不要据此猜测每次调用是否会分配新对象。
重复值要先决定删除一个还是全部
ArrayList<Integer> values = new ArrayList<Integer>(
Arrays.asList(2, 3, 2, 7)
);
values.removeAll(Arrays.asList(2));
System.out.println(values); // 预期 [3, 7]
这段代码明确删除全部数值 2,与 remove(Integer.valueOf(2)) 的“只删第一个”不同。不能只因为两种方法都能消除眼前问题,就在有重复数据的业务中互换。
如果业务本来要按索引删除,继续用 remove(int),并保证索引在 0 到 size() - 1 之间。删除后后面的元素会左移,不能继续套用删除前的位置表。
避免用未检查的 indexOf 结果删除
remove(indexOf(value)) 看似先找值再删除,但没有找到时 indexOf 返回 -1,随后按索引删除会越界。如果只是删除第一个匹配值,直接使用对象重载更合适;确实需要索引时,应在删除前显式确认它不小于零。
不要把异常处理成“忽略即可”。越界可能来自把元素值当索引,也可能是旧索引失效,两者需要不同修正。
用新建的样本列表核对三种情况:目标存在一次、存在多次、完全不存在。确认删除数量、剩余顺序和返回值都符合约定。生产数据已经误删时,修正重载不会补回元素;应从保留的原列表、数据库记录或审计信息恢复,避免凭当前下标猜测丢失内容。


