当前位置: 代码迷 >> Web前端 >> Iterator迭代器,不可浮光掠影
  详细解决方案

Iterator迭代器,不可浮光掠影

热度:467   发布时间:2012-08-10 12:19:33.0
Iterator迭代器,不可蜻蜓点水

对于java基础了解多少呢?对于Iterator迭代器,掌握多少嗯?是否真正会用了呢?

在做项目中,需求如下:后台传过来list对象,界面显示需要删除list的某一个对象。

解决办法如下:

第一种:其实后台直接传过来已经删除某个对象的list即可,在dao层的sql语句完成。界面直接循环list显示即可。

第二种:后台传过来完整的list对象,界面显示时,先删除list某一个对象,然后再循环显示删除后的list

本人使用的是第二种做法,因为项目是分工开发的,后台已经完成并已封装。其实仔细思考后,没哟必要在后台再添加一个方法,直接在业务逻辑层中或actionjsp中再次加工而已。

 list中删除一个对象,肯定是先遍历,然后找出不符合的,直接在集合中删除即可。

其中,java容器,Collection,Set,List,Map等等,这块,我曾经做过总结,感兴趣的可以浏览一下。当时做的总结,是把接口的分类,但没有涉及到其中的方法,add,remove,get等等。

首先看一下java代码:

    public static void main(String[] args) {
    List c=new ArrayList();
        c.add("测试迭代器");
        c.add("测试java容器");
        Iterator it=c.iterator();
        while(it.hasNext()){
            String test=(String)it.next();
            if("测试java容器".equals(test)){
                 c.remove(test);
            }
        }
            System.out.println(c);
    }

这段java代码,看出猫腻了吗?乍一看,思路完全正确啊。那结果应该会输出[测试迭代器]呀。可以结果却不是如此。

  执行这段java代码,抛出异常。 

    Exception in thread "main" java.util.ConcurrentModificationException
    at java.util.AbstractList$Itr.checkForComodification(Unknown Source)
    at java.util.AbstractList$Itr.next(Unknown Source)
    at TestIterator.main(TestIterator.java:22) 

 产生错误的原因在于没有正确理解Iterator迭代器。

  其实,迭代器是采用了快速失败的原理,一旦发现自己遍历的集合被修改,就像 c.remove(test);程序把集合c进行修改,则报以上的错误。其实这种错误经常在多线程中出现,一个线程在遍历集合,突然另一个线程把集合中的数据进行篡改。这种现象肯定是不允许出现的,报以上错误就是为了防止多线程共享资源发生资源争夺问题。

 

  那如何避免这个问题呢?如何删除呢?

  使用迭代器Iterator中的remove方法,Iterator迭代器一共三个方法,hasNext(),判断是否有下一个集合元素;Next(),返回的集合中下一个元素;remove()删除迭代器刚刚next的集合元素。

  真正理解了这三个方法,使用就灰常简单了。

  直接把c.remove(test);改成it.remove();即可。运行结果肯定必须也如愿以偿的是[测试迭代器];

  另外在上述代码中进行改动一下,运行结果又是如何的呢? 

    public static void main(String[] args) {
        List c=new ArrayList();
        c.add("测试迭代器");
        c.add("测试java容器");
        Iterator it=c.iterator();
        while(it.hasNext()){
            String test=(String)it.next();
            if("测试java容器".equals(test)){
                             test="测试成功";
            }
           }
        System.out.println(c);
    }

  运行结果是[测试迭代器,测试java容器]。咦,为何没有发生变化呢?又得要重新理解Iterator迭代器了。

  因为迭代器Iterator循环遍历集合元素时,并不是把集合元素给了迭代器变量test,而是把集合元素的值赋给了迭代器变量test,所以修改迭代器变量test的值时,并不是影响到集合元素。

   这种情况就如值传参和引用传参。值传参,不会影响到原来的变量。而引用传参,则会影响到原来的变量,因为引用传参是指向的同一个内存区域。

   通过这次异常,发现基础的重要性。同时也意识到,基础虽重要,理解也灰常重要。有些东西需要囫囵吞枣,走马观花,蜻蜓点水,不求甚解。但是有些东西必须做到咬文嚼字,耳熟能详,一清二楚,烂若披掌,了如指掌。

15楼qq10281845昨天 08:20
[code=java]npublic static void main(String[] args) {n List c=new ArrayList();n c.add("测试迭代器");n c.add("测试java容器");n Iterator it=c.iterator();n while(it.hasNext()){n String test=(String)it.next();n if("测试java容器".equals(test)){n test="测试成功";n }n }n System.out.println(c);n }n[/code]n表示对这个例子很不理解,在迭代的时候好像根本都没有对c操作,打印的结果肯定[测试迭代器,测试java容器],为什么会这样问呢?
Re: qq10281845昨天 09:52
求楼主解释!!
Re: llhhyy1989昨天 14:36
回复qq10281845nString test=(String)it.next(); n test="测试成功"; n这个迭代器循环赋值给迭代器变量了。
Re: qq10281845昨天 21:14
回复llhhyy1989n但是前面一直都没有对List c这个集合操作吧?它的值应该就是原本的值,而且迭代的Iterator it这个集合,两者直接没有直接对数据的操作,只是把c的值赋给it,在操作it的时候,没有对c做任何操作,打印[测试迭代器,测试java容器]这个结果,应该没问题,想不明白。继续求解释。。
Re: llhhyy1989昨天 22:55
回复qq10281845n(*^__^*) 嘻嘻……,你理解着对着呢。因为String test=(String)it.next(); 有的人曾说是吧集合元素给了test,这样,test改变,其对应的集合元素也发生变化,也就是部分人认为“测试java容器”被改成“测试成功”。其实不是,只是把集合元素的值给了test,所以test改变,不会影响其对应的集合元素。
Re: llhhyy198911小时前
回复llhhyy1989n有些人疑为输出:[测试迭代器,测试成功]。并且为了说明“ 因为迭代器Iterator循环遍历集合元素时,并不是把集合元素给了迭代器变量test,而是把集合元素的值赋给了迭代器变量test,所以修改迭代器变量test的值时,并不是影响到集合元素。”
14楼haizhijiaotianzhiya昨天 23:30
顶一个。。。
13楼xjc1278003262前天 17:11
给师姐顶了,先学习着,等待日后用
Re: llhhyy1989昨天 22:53
回复xjc1278003262n[e10] 呵呵,谢谢关注!
12楼liuyanlinglanq前天 17:09
支持
11楼liusong0605前天 17:08
很详细,谢谢分享!
10楼happyITer前天 16:54
发现问题,就是进步的开始,加油!!!
Re: llhhyy1989前天 16:55
回复happyITern说的很好!重要的是发现问题。(*^__^*) 嘻嘻……
9楼xqf309前天 16:53
有些不能蜻蜓点水[e01]
8楼lishehe前天 16:52
7楼haigegegege前天 16:52
好事要多磨。
6楼zlh6688前天 16:50
确实基础很重要,打基础需要一个过程。
Re: llhhyy1989前天 16:51
回复zlh6688n基础是一个人高发展,深发展的本钱。
5楼zhanglianhai555前天 16:40
虽然看不懂,但我支持你!!!!!
Re: llhhyy1989前天 16:49
回复zhanglianhai555n[e10] O(∩_∩)O谢谢您支持
4楼lfmilaoshi前天 16:39
有些东西需要囫囵吞枣,走马观花,蜻蜓点水,不求甚解。但是有些东西必须做到咬文嚼字,耳熟能详,一清二楚,烂若披掌,了如指掌。n宏观和微观。。。。米老师
3楼qq10281845前天 15:40
大概看明白楼主说的问题,后面输出c的值,感觉不怎么合适,如果是输出it的值这样应该可以更好的表达楼主的意思,楼主你觉得呢
Re: llhhyy1989前天 15:58
回复qq10281845n不是啊,因为部分人认为集合c发生变化了,应该输出c呀。其实c没有发生变化啊。呵呵,谢谢一直关注,互相交流哈。
2楼rankun203前天 15:35
哟西哟西,非常感谢迭代器一文,现在在学Jsp初步,有很多其他知识在学,但还是要经常来看看你们提高班的文章...嘿嘿.
Re: llhhyy1989前天 15:39
回复rankun203n谢谢支持哈![e10]
1楼smszhuang168前天 15:30
第二个例子要表达什么意思没太明白
Re: llhhyy1989前天 15:33
回复smszhuang168n因为迭代器Iterator循环遍历集合元素时,并不是把集合元素给了迭代器变量test,而是把集合元素的值赋给了迭代器变量test,所以修改迭代器变量test的值时,并不是影响到集合元素。
  相关解决方案