初始化一个集合
List<Integer> list = new ArrayList<>(Arrays.asList(1,2,3,4));
一、使用for循环进行删除 (正序遍历移除元素)
System.out.println("初始化集合大小:" + list.size());
for (int i = 0; i < list.size(); i++) {
Integer remove = list.remove(i);
System.out.println("下标:"+ i +"集合大小:" + list.size() + ":" + "集合元素:" + list);
}
观察输出:发现集合的size随着remove的次数在变化。
第一次:i < 0 size = 4
第二次:i < 3 size = 3
第三次:i < 2 size = 2 由于 2 < 2 是不成立的,所以for循环不在执行了。这样的话,元素就还剩下两个元素并没有删除。这是第一次坑。
第二个坑,在删除是时候,数组的下标是会变的,第一次的时候[1,2,3,4] 下标0的元素是1
第二次的时候[2,3,4] 下标0的元素是2 ,所以你会发现 第二次的时候 把3删除了 并没有删除2
1.1 升级一下操作
顺序循环时,删除当前位置的值,下一个值就会补到当前位置,所以需要执行i–操作;
for (int i=0; i<list.size(); i++) {
if (list.get(i) == 3) {
list.remove(i);
i--;
}
}
二、使用for循环进行删除 (倒序遍历移除元素)
for (int i = list.size()-1; i >= 0; i--) {
list.remove(i);
System.out.println("下标:"+ i +"集合大小:" + list.size() + ":" + "集合元素:" + list);
}
//i=3 i>=0 移除array[3] list[1,2,3] //i=2 i>=0 移除array[2] list[1,2] //i=1 i>=0 移除array[1] list[1] //i=0 i>=0 移除array[0] list[]
观察输出:倒序的移除结果是正确的。
三、使用foreach循环进行删除
for (Integer integer : list) {
list.remove(integer);
}
出现异常,原因比较多,移步到这篇:https://www.freesion.com/article/68581338545/
四、使用Iterator迭代器进行删除
Iterator<Integer> iterator = list.iterator();
while (iterator.hasNext()){
iterator.next();
iterator.remove();
System.out.println("Iterator遍历移除元素结果:" + list);
}
运行结果:运行正常。
删除总结:尽可能用迭代器来遍历,并使用迭代器的remove方法来删除元素。 用for循环的话,就使用倒序遍历删除元素。
Sublist的坑
一、【强制】ArrayList 的 subList 结果不可强转成 ArrayList,否则会抛出 ClassCastException 异 常:java.util.RandomAccessSubList cannot be cast to java.util.ArrayList。
ArrayList<Integer> arrayList = new ArrayList<>();
arrayList.add(1);
arrayList.add(2);
arrayList.add(3);
arrayList.add(4);
ArrayList<Integer> list = (ArrayList<Integer>) arrayList.subList(1, 3);
说明:subList 返回的是 ArrayList 的内部类 SubList,并不是ArrayList ,而是 ArrayList 的一个视图,对于SubList子列表的所有操作最终会反映到原列表上。
二、在subList场景中,高度注意对父集合元素的增加或删除,均会导致子列表的遍历、增加、删除产生 ConcurrentModificationException 异常。
List<Integer> arrayList = new ArrayList<>();
arrayList.add(1);
arrayList.add(2);
arrayList.add(3);
arrayList.add(4);
arrayList.add(5);
List<Integer> list = arrayList.subList(1, 3);
for (Integer integer : list) {
System.out.println(" "+integer);
}
System.out.println("进行元素的删除操作");
arrayList.remove(0);
System.out.println("list元素:" + list);
ArrayList中有个protected transient int modCount = 0; 用来记录当前ArrayList被修改的次数。
比如add(),remove()等都会导致modeCount增加: ArrayList.subList()会生成一个SubList的对象,SubList中有个对应modCount同步ArrayList中的modeCount: SubList对象每次再遍历时,会将自己的modeCount与ArrayList的modeCount进行对比,如果两个值不一样就会报异常:ConcurrentModificationException