黑马程序员技术交流社区

标题: 集合框架中的小问题,求帮忙 [打印本页]

作者: 曾林魁    时间: 2013-6-1 23:06
标题: 集合框架中的小问题,求帮忙
本帖最后由 曾林魁 于 2013-6-2 13:08 编辑
  1. import java.util.*;
  2. class CollectionDemo
  3. {
  4. public static void main(String[] args)
  5. {
  6. mothedGet();
  7. }
  8. static void mothedGet()
  9. {
  10. ArrayList<String> a1 =new ArrayList<String>();
  11. a1.add("java1");
  12. a1.add("java4");
  13. a1.add("java2");
  14. a1.add("java3");

  15. sop(a1);

  16. for (ListIterator it = a1.listIterator();it.hasNext(); )
  17. { //sop(it.hasPrevious());
  18. Object obj = it.next();
  19. if(obj.equals("java2"))
  20. it.add("java5");
  21. it.set("j");
  22. }
  23. sop(a1);
  24. sop(a1.size());
  25. }
  26. public static void sop(Object a)
  27. {
  28. System.out.println(a);
  29. }
复制代码
这个他怎么是编译失败?自己感觉没错啊!!大家帮忙看看吧! 谢谢了
作者: 花开花落总相似    时间: 2013-6-1 23:28
   我也没有试验就给你说一下吧
   我觉得你是增强for 循环错了 和循环体里面的内容有问题
ListIterator <String>it = a1.listIterator();
whie(it.hasNext){
String s = it.next();
if(s.equal("java2"))
al.add("java5");
al.set()   这个我不知道你要替换什么东西  所以你自己搞     我直说吧  你那几个东西全是错的   增强for循环及循环圈里面的东西全部改掉
}
作者: 于腾飛    时间: 2013-6-2 00:27
22行错误代码  it是跌带出的元素,不会又add方法;
用for循环迭代,循环结束,局部变量消失,你尝试修改集合中的元素,会报ConcurrentModificationException
作者: 刘国强    时间: 2013-6-2 00:54
本帖最后由 刘国强 于 2013-6-2 01:03 编辑

楼主,程序运行后报了一个异常:
Exception in thread "main" java.lang.IllegalStateException
at java.util.AbstractList$ListItr.set(AbstractList.java:408)
at abc.CollectionDemo.mothedGet(CollectionDemo.java:33)
at abc.CollectionDemo.main(CollectionDemo.java:10)


查看JDK文档,ListIterator集合的set方法,如下图:


注意看红圈部分,还有红线话的部分的异常信息,出现这个异常是因为既没有调用 next 也没有调用 previous,或者在最后一次调用 next 或 previous 后调用了 remove 或 add。
集合文档对此方法的说明:用指定元素替换 next 或 previous 返回的最后一个元素(可选操作)。只有在最后一次调用 next 或 previous 后既没有调用 ListIterator.remove 也没有调用 ListIterator.add 时才可以进行该调用。

所以对楼主的代码进行了修改,将it.set("j"); 放在了if语句的前面,这时再运行,就不会再出现异常

修改后代码
  1. package abc;
  2. import java.util.*;

  3. class CollectionDemo

  4. {

  5. public static void main(String[] args)
  6. {
  7.   mothedGet();

  8. }

  9. static void mothedGet()
  10. {

  11.   ArrayList<String> a1 =new ArrayList<String>();</p><p>  a1.add("java1");
  12.   a1.add("java4");
  13.   a1.add("java2");
  14.   a1.add("java3");

  15.   sop(a1);

  16.   for (ListIterator it = a1.listIterator();it.hasNext(); )
  17.   { //sop(it.hasPrevious());

  18.    Object obj = it.next();
  19.    
  20.    it.set("j");
  21.    if(obj.equals("java2"))
  22.     it.add("java5");
  23.   
  24.   }

  25.   sop(a1);
  26.   sop(a1.size());

  27. }

  28. public static void sop(Object a)
  29. {
  30.   System.out.println(a);
  31. }
  32. }
复制代码
此时运行就不会再产生异常。可以正常运行,产生结果。

因此,楼主代码主要是,it.set()方法放的位置有问题





作者: 狂飙的yellow.co    时间: 2013-6-2 07:06
哥们,你看看你的程序错误的地方在25行和第9行



然后分析了一下,不知道哥们想的到啥样的结果,如果是添加的话,代码这样就可以了
  1. for (ListIterator it = a1.listIterator(); it.hasNext();) { // sop(it.hasPrevious());
  2.                         Object obj = it.next();
  3.                         if (obj.equals("java2"))
  4.                                 it.add(obj);
  5.                 }
复制代码
运行的结果是:
  1. [java1, java4, java2, java3]
  2. [java1, java4, java2, java2, java3]
  3. 5
复制代码
如果是改变元素的话,这样就可以了
  1. for (ListIterator it = a1.listIterator(); it.hasNext();) { // sop(it.hasPrevious());
  2.                         Object obj = it.next();
  3.                         if (obj.equals("java2"))
  4.                                 it.set("j");
  5.                 }
复制代码
运行的结果是:
  1. [java1, java4, java2, java3]
  2. [java1, java4, j, java3]
  3. 4
复制代码
哥们这时可能就要问为啥我的就不行呢。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。对吧

楼上的大神,回答得很正确

集合文档对此方法的说明:用指定元素替换 next 或 previous 返回的最后一个元素(可选操作)。只有在最后一次调用 next 或 previous 后既没有调用 ListIterator.remove 也没有调用 ListIterator.add 时才可以进行该调用。

不过结果是不堪设想
  1. for (ListIterator it = a1.listIterator(); it.hasNext();) { // sop(it.hasPrevious());
  2.                         Object obj = it.next();
  3.                                 it.set("j");
  4.                         if (obj.equals("java2"))
  5.                                 it.add(obj);
  6.                
  7.                 }
复制代码
结果是
  1. [java1, java4, java2, java3]
  2. [j, j, j, java2, j]
  3. 5
复制代码
将前面的3个,都set成了 j

作者: Super_Class    时间: 2013-6-2 07:31
for (ListIterator it = a1.listIterator();it.hasNext(); )
{ //sop(it.hasPrevious());
Object obj = it.next();
if(obj.equals("java2"))
it.add("java5");
it.set("j");
}

迭代的时候不能对这个集合进行操作。

解决办法:

方法一:使用迭代器的子接口:ListIterator 列表迭代器
                                系列表迭代器,允许程序员按任一方向遍历列表、迭代期间修改列表,并获得迭代器在列表中的当前位置。ListIterator
                                没有当前元素;它的光标位置
                                始终位于调用 previous() 所返回的元素和调用 next() 所返回的元素之间。
         
                                Iterator<String> iterator = list.iterator();
                                改为  ListIterator iterator = list.listIterator();

                        方法二:使用集合的实现子类:CopyOnWriteArrayList
                                List list = new ArrayList(); 改为
                                List list = new CopyOnWriteArrayList();
                                class CopyOnWriteArrayList<E>extends Object implements List<E>,
                                                                                                                                        RandomAccess,
                                                                                                                                        Cloneable,
                                                                                                                                        SerializableArrayList
                                的一个线程安全的变体,其中所有可变操作(add、set 等等)都是通过对底层数组进行一次新的复制来实现的。

作者: 黑马一刘昭    时间: 2013-6-2 11:20
二楼的图片,你一看估计就明白了,我最初看的时候也是感觉迭代器的set出了问题,运行一下确实,你做题的 时候常查api,按照规则来办事。五楼回复的应该很详细了。不过我最初修改只是最简单的:把你的23行换成了a1.set(1,"j");别的改法都对!加油黑马人!




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