黑马程序员技术交流社区

标题: ArrayList遍历出错 [打印本页]

作者: yaohsieh    时间: 2013-12-26 21:45
标题: ArrayList遍历出错
  1. import java.util.ArrayList;
  2. import java.util.Collection;
  3. import java.util.Iterator;

  4. public class Test {
  5.         public static void main(String[] args) {

  6.                 Collection c = new ArrayList();
  7.                 String s1 = new String("超人");
  8.                 String s2 = new String("蜘蛛侠");
  9.                 String s3 = new String("蝙蝠侠");
  10.                 c.add(s1);
  11.                 c.add(s2);
  12.                 c.add(s3);
  13.                 Iterator it = c.iterator();
  14.                 while (it.hasNext()) {
  15.                         String s = (String) it.next();
  16.                         System.out.println(s);
  17.                         if (s.equals("蝙蝠侠"))
  18.                                 c.remove(s);
  19.                 }
  20.         }
  21. }
复制代码
为啥报错呢?
错误信息:
  1. 超人
  2. Exception in thread "main" 蜘蛛侠
  3. 蝙蝠侠
  4. java.util.ConcurrentModificationException
  5.         at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:859)
  6.         at java.util.ArrayList$Itr.next(ArrayList.java:831)
  7.         at com.yaohsieh.Test.main(Test.java:19)
复制代码




作者: (0.0)’    时间: 2013-12-26 22:05
1、解决方案一:
  1. Collection c = new ArrayList();
  2.                 String s1 = new String("超人");
  3.                 String s2 = new String("蜘蛛侠");
  4.                 String s3 = new String("蝙蝠侠");
  5.                 c.add(s1);
  6.                 c.add(s2);
  7.                 c.add(s3);
  8.                                 String str = null;
  9.                 Iterator it = c.iterator();
  10.                 while (it.hasNext()) {
  11.                         String s = (String) it.next();
  12.                         System.out.println(s);
  13.                         if (s.equals("蝙蝠侠"))
  14.                                                         str = s;
  15.                                 //c.remove();不可以在迭代的时候去直接使用集合中删除和添加的方法

  16.                 }
  17.                                 if(str != null){
  18.                                         c.remove(str);
  19.                                 }
  20.                                 System.out.println(c);
复制代码

2、解决方案二:
  1. Collection c = new ArrayList();
  2.                 String s1 = new String("超人");
  3.                 String s2 = new String("蜘蛛侠");
  4.                 String s3 = new String("蝙蝠侠");
  5.                 c.add(s1);
  6.                 c.add(s2);
  7.                 c.add(s3);
  8.                 Iterator it = c.iterator();
  9.                 while (it.hasNext()) {
  10.                         String s = (String) it.next();
  11.                         System.out.println(s);
  12.                         if (s.equals("蝙蝠侠"))
  13.                                                         it.remove();  //可以使用迭代器中的方法增、删                 
  14.                 }       
  15.                                 System.out.println(c);
复制代码

作者: 高亮亮    时间: 2013-12-26 22:22
并发修改异常.
这就是体现了ArrayList是线程不安全的.就是你在迭代器迭代的时候,不能通过集合本身,或者迭代器来对集合内容进行结构上的修改(长度).因为这样会进入一个矛盾的境地.
关于这个不好理解的话,举个例子,就是你在对一箱啤酒点数的时候,有人来拿走或者放进去啤酒,你是不是肯定得不到正确的总数?所以就会异常了.
关于修改方法,两种,一是用for循环再循环的时候进行增减.还有一种就是用列表迭代器,就是ListIterator进行迭代中修改,因为ListIterator中提供了增删功能.
代码楼上用for的是对的,不过他的第二种方法如果把Iterator换成ListIterator lit=c.listIterator();就更好了,因为列表迭代器功能更多.
作者: tuanjie    时间: 2013-12-26 23:21
对集合使用Iterator迭代器遍历集合时,如果在遍历的过程中对集合进行操作(增,删、改),需要使用迭代器里面的方法进行操作,使用集合对象进行操作会出现异常。集合对象和迭代器对象分别是两个对象,在迭代的过程中,使用集合对象进行增、删、改操作时,会改变集合的大小,但是迭代器对象并不知道集合的大小已将改变,就会按照原先集合的大小进行迭代输出,就会出现异常问题了,要是对集合进行操作,在操作集合的同时需要告诉迭代器,集合已经改变了,就需要使用迭代器本身自带的增、删、改操作对迭代中的集合进行操作。
代码修改一下,就没有问题了,代码如下:
  1. import java.io.IOException;
  2. import java.util.ArrayList;
  3. import java.util.Collection;
  4. import java.util.Iterator;

  5. public class Test {

  6.     public static void main(String[] args) throws IOException {
  7.         Collection c = new ArrayList();
  8.         String s1 = new String("超人");
  9.         String s2 = new String("蜘蛛侠");
  10.         String s3 = new String("蝙蝠侠");
  11.         c.add(s1);
  12.         c.add(s2);
  13.         c.add(s3);
  14.         Iterator it = c.iterator();
  15.         while (it.hasNext()) {
  16.             String s = (String) it.next();
  17.             System.out.println(s);
  18.             if (s.equals("蝙蝠侠"))
  19.                 it.remove();
  20.         }
  21.         System.out.println("--------------------------");
  22.         for(Object obj : c){
  23.             String str = (String)obj;
  24.             System.out.println(str);
  25.         }
  26.     }
  27. }

复制代码




作者: yaohsieh    时间: 2013-12-27 00:27
(0.0)’ 发表于 2013-12-26 22:05
1、解决方案一:

2、解决方案二:

明白了,两个解决方案很到位!
作者: yaohsieh    时间: 2013-12-27 00:30
高亮亮 发表于 2013-12-26 22:22
并发修改异常.
这就是体现了ArrayList是线程不安全的.就是你在迭代器迭代的时候,不能通过集合本身,或者迭代 ...

啤酒点数例子很生动!
还学了for循环和ListIterator两招!




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