zoukankan      html  css  js  c++  java
  • Java遍历List并删除某些元素

    Java遍历List并删除某些元素

    ​ 在阿里的Java编程规约中有一条:【强制】不要在foreach循环里进行元素的remove/add操作。remove元素请使用Iterator方式,如果并发操作,需要对Iterator对象加锁。

    ​ 这里不禁要问为什么?

    ​ 首先来试一下,遍历List时删除元素究竟行不行:

    public class IteratorTest {
    
    	public static void singleThreadRemove1(){
    		List<String> list = new ArrayList<>();
    		list.add("1");
    		list.add("2");
    		list.add("3");
    		for (String l : list){
    			if ("1".equals(l)){
    				list.remove(l);
    			}
    		}
    		System.out.println(list);
    	}
    
    	public static void main(String[] args){
    		singleThreadRemove1();
    	}
    
    }
    

    运行结果:

    Exception in thread "main" java.util.ConcurrentModificationException
    	at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:909)
    	at java.util.ArrayList$Itr.next(ArrayList.java:859)
    	at blog.IteratorTest.singleThreadRemove1(IteratorTest.java:19)
    	at blog.IteratorTest.main(IteratorTest.java:28)
    
    Process finished with exit code 1
    

    定位报错日志可以发现,遍历每个元素都会调用next()方法,next()方法首先有一个校验:

    final void checkForComodification() {
                if (modCount != expectedModCount)
                    throw new ConcurrentModificationException();
            }
    

    这里modCount是指list实际修改的次数,expectedModCount是预计修改的次数,调用List的remove()方法只会增加modCount的值,而不会增加expectedModCount,也就是说这是Java在让我们避免在for循环中删除list的元素。

    ​ 要想知道为什么要避免这种操作很简单,将上面程序中条件改为“当元素值等于‘2’时删除元素”,此时会发现程序可以正常运行!当list遍历完第二个元素时,这时准备进入第三个元素,然而list的元素数量已经减少,第三个索引位置上没有元素,循环结束。这是多么荒唐的事啊,循环遍历元素,明明有一个元素没有走到,循环却正常结束。

  • 相关阅读:
    Single Number 解答
    Minimum Size Subarray Sum 解答
    Valid Anagram 解答
    Count Primes 解答
    fullCalendar 日历显示每天数据调用方法实践
    jqGrid列的统计
    关于 asp.net Web Api 上传文件请求内容过大404错误记录
    My97DatePicker只显示月份
    js 宏微任务执行顺序
    git 等官网下载慢方法
  • 原文地址:https://www.cnblogs.com/wutongblog/p/11637941.html
Copyright © 2011-2022 走看看