黑马程序员技术交流社区

标题: 关于用迭代器遍历集合过程中删除元素的问题!求解 [打印本页]

作者: 赵永康    时间: 2012-9-21 19:26
标题: 关于用迭代器遍历集合过程中删除元素的问题!求解
毕老师在讲解集合的时候,说再用迭代器遍历的时候,不能够增加和删除集合中的元素。我特意试了一下!以下是我自己敲的一段代码,请大家看看
import java.util.*;
class CollectionsTest
{

public static void main(String[] args)
{
  ArrayList all=new ArrayList();
  all.add("zhangsan");
  all.add("lisi");
  all.add("wangwu");
  Iterator it=all.iterator();
  while(it.hasNext())
  {
   String str=(String)it.next();
   if("lisi".equals(str))//当我把这里的lisi改成zhangsan或者wangwu的时候,运行的时候,就会报异常,但是当时lisi的时候怎么不会
   {
    all.remove(str);
   }
  }
  System.out.println(all);//但是lisi的时候打印结果是zhansan,wangwu
}
}
想请问问各位这是为什么???

作者: 赵宇    时间: 2012-9-21 19:44
hasNext();判断是否有 下个元素 如果有下个元素返回true ,如果没有下个元素返回false next():返回下个元素。
remove() :从迭代器指向的 collection 中移除迭代器返回的最后一个元素
第一次你使用while循环后hasNext()指针已经制定到最后,所以你第二次再次判断的时候指针后面已经不再有元素了
所以会报异常。
  System.out.println(all);//但是lisi的时候打印结果是zhansan,wangwu  这很正常 lisi被你干掉了
作者: 宁振庄    时间: 2012-9-21 20:03
Iterator 被创建之后会建立一个指向原来对象的单链索引表,当原来的对象数量发生变化时,这个索引表的内容不会同步改变,所以当索引指针往后移动的时候就找不到要迭代的对象,所以 Iterator 会马上抛出 java.util.ConcurrentModificationException 异常。
  
  你用 all.remove(str) 实际上就是改变了原来集合的数量,这时候Iterator 索引表内容并没有同步改变,所以会报错。如果想正确移除集合中的元素,你这里应该用 it.remove()。
  至于为什么你lisi的时候不报错,那应该是它算法的问题,3个元素里面移除中间那个元素而Iterator的索引表还能找得到,就没有报错。而你再添加一个元素弄成4个,再试试,一样会报错。

作者: 王小闲7    时间: 2012-9-21 20:41
在你对list遍历的时候是不能删除元素的(具体原因我也看不懂),我看视频有这方面的内容,解决方法是将要删除的内容加到另一个list中,等遍历完了再将该list(该list是包含要删除的list)删除就可以了
作者: 赵永康    时间: 2012-9-21 20:51
求解啊  哪位能解释下吗  以后到底敢不敢删除元素啊
作者: 宁振庄    时间: 2012-9-21 20:55
赵永康 发表于 2012-9-21 20:51
求解啊  哪位能解释下吗  以后到底敢不敢删除元素啊

都解释过了啊,你遍历的时候要删除某个元素不要用原来集合的remove(Object o)方法,要用迭代器的remove()方法,在你的代码里就是不要用 all.remove(str);  ,而是用 it.remove()
作者: 赵永康    时间: 2012-9-21 21:14
宁振庄 发表于 2012-9-21 20:55
都解释过了啊,你遍历的时候要删除某个元素不要用原来集合的remove(Object o)方法,要用迭代器的remove() ...

你说的是Linkedlist集合有个专门的自己的迭代器,它里面有删除和增加的方法,我现在的集合石Arrarylist的
作者: 吴兵    时间: 2012-9-21 22:27
本帖最后由 吴兵 于 2012-9-21 22:44 编辑

  Iterator it=all.iterator();
  while(it.hasNext())
  {
   String str=(String)it.next();//迭代器正在进行取出操作,这个同时再用集合的功能操作该元素,就有可能产生安全隐患;                                                           
                                          //
这就叫并发访问,不能对同一个元素同时进行多种操作!
                                          //所以抛出ConcurrentModificationException异常--当方法检测到对象的并发修改,但不允许这种修改时,抛出此异常。
   if("lisi".equals(str))
   {
    all.remove(str);// 当为"lisi"时it.next()指向"wangwu";而all集合操作的是"lisi",所以不存在安全隐患,不抛出异常)     
                           //若想修改则把此处改为it.remove();  迭代的过程中要么全用迭代器的功能,要么全用集合的功能,这样就没有问题啦
   }
  }
  System.out.println(all);

作者: 赵永康    时间: 2012-9-21 22:36
吴兵 发表于 2012-9-21 22:27
Iterator it=all.iterator();
  while(it.hasNext())
  {

哦 这样啊  我在验证一下




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2