zoukankan      html  css  js  c++  java
  • List删除操作

    在Java中对列表进行删除操作时,如果使用不当的话,会产生java.util.ConcurrentModificationException异常。

        @Test
        public void remove2() {
    
            // java.util.ConcurrentModificationException
    
            List<Integer> list = new ArrayList<>();
            list.add(1);
            list.add(2);
            list.add(3);
            list.add(4);
            list.add(5);
    
            for (Integer number : list) {
                if (number % 2 == 0) {
                    list.remove(number);
                }
            }
            System.out.println(Arrays.toString(list.toArray()));
        }
    

    运行上边的测试代码,产生如下异常

    java.util.ConcurrentModificationException
    	at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:909)
    	at java.util.ArrayList$Itr.next(ArrayList.java:859)
    	at com.st.learning.algorithm.ListRemoveTest.remove2(ListRemoveTest.java:51)
    	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    	at java.lang.reflect.Method.invoke(Method.java:498)
    	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
    	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
    	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    	at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    	at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
    	at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
    	at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
    	at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
    

    查看生成的字节码可以看到,

    List<Integer> list = new ArrayList();
            list.add(1);
            list.add(2);
            list.add(3);
            list.add(4);
            list.add(5);
            Iterator var2 = list.iterator();
    
            while(var2.hasNext()) {
                Integer number = (Integer)var2.next();
                if (number % 2 == 0) {
                    list.remove(number);
                }
            }
    
            System.out.println(Arrays.toString(list.toArray()));
    

    foreach循环在这里使用的是Iterator实现,使用了hasNext()和next()方法。

    在ArrayList中,next()方法实现如下:

    上方标红处即为代码报错处,实现如下:

    上图中对比了modCount和expectedModCount两个字段的值,不一致时,发生了异常。

    在刚开始时,代码中的modCount和expectedModCount均为5,在执行到下方代码时,modCount发生了变化,编程了6,

    list.remove(number);
    


    这也就是问题产生的原因

    列表的删除方法

    • iterator的remove()方法
        @Test
        public void remove3() {
            List<Integer> list = new ArrayList<>();
            list.add(1);
            list.add(2);
            list.add(3);
            list.add(4);
            list.add(5);
    
            Iterator<Integer> iterator = list.iterator();
    
            while (iterator.hasNext()) {
                if (iterator.next() % 2 == 0) {
                    iterator.remove();
                }
            }
            System.out.println(Arrays.toString(list.toArray()));
        }
    


    使用iterator删除时,会将modCount的值赋值给expectedModCount,所有不会发生以上问题

  • 相关阅读:
    matplotlib-形状
    matplotlib-区域填充
    C++文件操作
    画数学公式
    文字
    画注释
    Doubango简介-sip
    boost的asio接收单路大数据量udp包的方法
    Boost.Asio基本原理(CSDN也有Markdown了,好开森)
    boot asio 非阻塞同步编程---非阻塞的accept和receive。
  • 原文地址:https://www.cnblogs.com/lzw-st/p/13202136.html
Copyright © 2011-2022 走看看