List循环遍历Remove的坑和SubList的坑

初始化一个集合

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

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值