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


    初始化一个集合

    List list = new ArrayList<>(Arrays.asList(1,2,3,4));

    一、使用for循环进行删除 (正序遍历移除元素)

    1. System.out.println("初始化集合大小:" + list.size());
    2. for (int i = 0; i < list.size(); i++) {
    3. Integer remove = list.remove(i);
    4. System.out.println("下标:"+ i +"集合大小:" + list.size() + ":" + "集合元素:" + list);
    5. }

     观察输出:发现集合的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–操作;

    1. for (int i=0; i
    2. if (list.get(i) == 3) {
    3. list.remove(i);
    4. i--;
    5. }
    6. }

     

    二、使用for循环进行删除 (倒序遍历移除元素)

    1. for (int i = list.size()-1; i >= 0; i--) {
    2. list.remove(i);
    3. System.out.println("下标:"+ i +"集合大小:" + list.size() + ":" + "集合元素:" + list);
    4. }

    //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循环进行删除

    1. for (Integer integer : list) {
    2. list.remove(integer);
    3. }

     出现异常,原因比较多,移步到这篇:https://www.freesion.com/article/68581338545/

    四、使用Iterator迭代器进行删除 

    1. Iterator iterator = list.iterator();
    2. while (iterator.hasNext()){
    3. iterator.next();
    4. iterator.remove();
    5. System.out.println("Iterator遍历移除元素结果:" + list);
    6. }

     运行结果:运行正常。

    删除总结:尽可能用迭代器来遍历,并使用迭代器的remove方法来删除元素。 用for循环的话,就使用倒序遍历删除元素。

    Sublist的坑

       一、【强制】ArrayList 的 subList 结果不可强转成 ArrayList,否则会抛出 ClassCastException 异 常:java.util.RandomAccessSubList cannot be cast to java.util.ArrayList。

    1. ArrayList arrayList = new ArrayList<>();
    2. arrayList.add(1);
    3. arrayList.add(2);
    4. arrayList.add(3);
    5. arrayList.add(4);
    6. ArrayList list = (ArrayList) arrayList.subList(1, 3);

    说明:subList 返回的是 ArrayList 的内部类 SubList,并不是ArrayList ,而是 ArrayList 的一个视图,对于SubList子列表的所有操作最终会反映到原列表上。 

    二、在subList场景中,高度注意对父集合元素的增加或删除,均会导致子列表的遍历、增加、删除产生 ConcurrentModificationException 异常。

    1. List arrayList = new ArrayList<>();
    2. arrayList.add(1);
    3. arrayList.add(2);
    4. arrayList.add(3);
    5. arrayList.add(4);
    6. arrayList.add(5);
    7. List list = arrayList.subList(1, 3);
    8. for (Integer integer : list) {
    9. System.out.println(" "+integer);
    10. }
    11. System.out.println("进行元素的删除操作");
    12. arrayList.remove(0);
    13. 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

  • 相关阅读:
    简述for in 和 for of 的区别
    代码随想录——图论一刷day02
    使用 Navicat 工具查看 SQLite 数据库中的 PNG 图片
    autojs(意图篇之startActivity)
    【现代机器人学】学习笔记一:位形空间
    变分自编码器(VAES)
    为什么我们如此热爱Python
    开源文档预览项目 kkFileView (9.9k star) ,快速入门
    ORA-00257: Archiver error. Connect AS SYSDBA only until resolved错误解决
    深入理解Spring Boot Starter:概念、特点、场景、原理及自定义starter
  • 原文地址:https://blog.csdn.net/qq_42217363/article/details/127102360