>>分享Java编程技术,对《Java面向对象编程》等书籍提供技术支持 书籍支持  卫琴直播  品书摘要  在线测试  资源下载  联系我们
发表一个新主题 开启一个新投票 回复文章 您是本文章第 29112 个阅读者 刷新本主题
 * 贴子主题:  java List列表中删除元素的正确处理方法 回复文章 点赞(0)  收藏  
作者:sunshine    发表时间:2017-07-13 12:51:15     消息  查看  搜索  好友  邮件  复制  引用

  public void testIterator (){  
        //测试ArrayList迭代过程中删除元素,  
        //避免抛出 java.util.ConcurrentModificationException  
        List<User> list  = new ArrayList<User>();  
        for(int i = 0 ; i < 10 ; i ++){  
            list.add(new User(i+""));  
        }  
        for(User temp:list){  
            if(Integer.parseInt(temp.name) % 2 == 0){  
                list.remove(temp);   //这里引起异常,这种迭代方式新增删除都会引起异常  
            }  
            System.out.print(temp.name + ",");  
        }  
        System.out.println("=====");  
        Iterator<User> it = list.iterator();  
        while(it.hasNext()){        //正确做法  
            //System.out.println(it.hasNext());  
            User temp = it.next();    
            if(Integer.parseInt(temp.name) % 2 == 0){  
                it.remove();  
            }  
        }  
          
        for(User temp:list){  
            System.out.print(temp.name + ",");  
        }  
          
          
    }  


class User{  
   String name = "";  
   public User(String name){  
       this.name = name;  
   }  
}  

问题分析:从API中可以看到List等Collection的实现并没有同步化,如果在多线程应用程序中出现同时访问,而且出现修改操作的时候都要求外部操作同步化;调用Iterator操作获得的Iterator对象在多线程修改Set的时候也自动失效,并抛出java.util.ConcurrentModificationException。这种实现机制是fail-fast,对外部的修改并不能提供任何保证。

Iterator是工作在一个独立的线程中,并且拥有一个 mutex锁,就是说Iterator在工作的时候,是不允许被迭代的对象被改变的。Iterator被创建的时候,建立了一个内存索引表(单链表),这 个索引表指向原来的对象,当原来的对象数量改变的时候,这个索引表的内容没有同步改变,所以当索引指针往下移动的时候,便找不到要迭代的对象,于是产生错误。List、Set等是动态的,可变对象数量的数据结构,但是Iterator则是单向不可变,只能顺序读取,不能逆序操作的数据结构,当 Iterator指向的原始数据发生变化时,Iterator自己就迷失了方向。


解决办法:调用其接口即Irerator的remove方法。

Iterator<User> it = list.iterator();  
while(it.hasNext()){        //正确做法  
//System.out.println(it.hasNext());  
User temp = it.next();    
if(Integer.parseInt(temp.name) % 2 == 0){  
    it.remove();  
}  


程序猿的技术大观园:www.javathinker.net
  Java面向对象编程-->变量的作用域和初始化
  JavaWeb开发-->使用过滤器
  JSP与Hibernate开发-->Spring、JPA与Hibernate的整合
  Java网络编程-->通过JDBC API访问数据库
  精通Spring-->
  Vue3开发-->Vue Router路由管理器
  [分享]遊藝場開分員會很難嗎?原來工作項目是這些!
  java的三种随机数生成方式
  类连接阶段的验证原理
  Java Optional 解决空指针异常总结
  Java 语言中十大“坑爹”功能!
  用注解去代替if-else的技巧
  购书咨询
  请求大佬们的帮助
  分布式锁的原理和实现
  NoClassDefFoundError和ClassNotFoundException的区别
  Java读取大文件的高效率实现_java大文件
  正则表达式:运算符优先级
  Java设计模式:备忘录模式
  Java设计模式:组合模式
  5个非常有挑战性的Java面试题
  更多...
 IPIP: 已设置保密
楼主      
1页 0条记录 当前第1
发表一个新主题 开启一个新投票 回复文章


中文版权所有: JavaThinker技术网站 Copyright 2016-2026 沪ICP备16029593号-2
荟萃Java程序员智慧的结晶,分享交流Java前沿技术。  联系我们
如有技术文章涉及侵权,请与本站管理员联系。