黑马程序员技术交流社区

标题: 迭代器遍历元素的问题 [打印本页]

作者: 依然超级赛亚人    时间: 2014-8-7 16:06
标题: 迭代器遍历元素的问题
本帖最后由 依然超级赛亚人 于 2014-8-13 08:06 编辑

今天在做迭代器相关的练习时,我在用while遍历元素之后又在下面加了一个同样的while语句,结果没有看到我预想中的打印两次结果,而且编译和运行都没报错,就是没打印出两次结果,好像只执行了一个while。想了半天不知怎么回事,想在论坛中请教一下大家,如下面代码:


import java.util.*;
class IteratorTest02
{
        public static void main(String[] args)
        {
                Person p1 = new Person("张三",28);
                Person p2 = new Person("李四",35);
                Person p3 = new Person("王五",38);
                Person p4 = new Person("张三",28);

                ArrayList<Person> array = new ArrayList<Person>();
                array.add(p1);
                array.add(p2);
                array.add(p3);
                array.add(p4);
               
                Iterator<Person> it = array.iterator();
                while(it.hasNext()){
                        sop(it.next());
                }
                //-------------------------------问题所在:又加了一个while语句,可是似乎没有执行...
                while(it.hasNext()){
                        sop(it.next());
                }
             //-----------------------------------------------------
        }
        //定义了一个打印方法,可以打印各种类型的数据。
        public static void sop(Object obj){
                System.out.println(obj);
        }
}
//自定义了一个Person类,因为它本身不像String类那样重写了toString()方法,所以我自己已经重写。
class Person
{
        private String name;
        private int age;
        Person(String name,int age){
                this.name=name;
                this.age=age;
        }
        public String getName(){
                return name;
        }
        public int getAge(){
                return age;
        }
        //重写了toString()方法
        public String toString() {
                return ""+ name +"--"+age;
        }
}


作者: 暗夜星辰    时间: 2014-8-7 16:14
楼主可以尝试下再用add方法加入一个元素,看看有没有抛异常
作者: 陶圣虎    时间: 2014-8-7 16:17
这个是因为迭代器指针问题。指针第一次已经运行到迭代器的最末尾位置,当第二次循环再次询问是否有hasNext的时候,肯定是没有元素的。List的迭代器有个向前遍历的方法,hasPrevious(),当指针运行到末尾时,问前面是否有元素,前面就有了。你可以试下,就可以打印两遍了。
作者: rolling-stone    时间: 2014-8-7 16:43
迭代器本质上是指针,迭代的时候指针不段的向后判断,你第一个while已经将指针移到最后面了,第二个while再循环,指针还是在最后,所以不会执行循环体的.
作者: icris    时间: 2014-8-7 16:49
第二个 while(it.hasNext()){} == while(false){}
作者: zz_job    时间: 2014-8-7 17:28
因为第一个迭代器的指针已经指向集合的末尾了,因此你的第二个while循环实际上判断条件始终为假,因为it.hasNext()的值已经被第一个while循环判定为假并终止循环,那么第二个循环一接收到就已经是假了  自然就不会再运行了。
作者: 左脑想你    时间: 2014-8-7 18:20
每一个next指针都会向后一个第一个循环过后指针在最后的位置,第二个循环的条件判断是指针还是在最后也就是it.hasnext()为false所以不会进入第二个while循环
作者: 王洪涛    时间: 2014-8-7 18:24
就像同步了一样
作者: 继续悲伤    时间: 2014-8-7 20:50
你在第一次遍历完以后再添加元素试试!!
作者: /aiq玩完?/aiq    时间: 2014-8-7 20:54
陶圣虎 发表于 2014-8-7 16:17
这个是因为迭代器指针问题。指针第一次已经运行到迭代器的最末尾位置,当第二次循环再次询问是否有hasNext ...

回答的很对。学到了,第二个while(it.hasNext)//为false,执行不到了用hasPrevious倒着取一次不就两次了,嘿嘿
作者: 依然超级赛亚人    时间: 2014-8-7 21:28
暗夜星辰 发表于 2014-8-7 16:14
楼主可以尝试下再用add方法加入一个元素,看看有没有抛异常

恩啊,问题已经解决了,就如楼下所说,这是指针的问题,我忽略了这一点,以为上面遍历之后,指针会自动恢复成原来的情况。:handshake
作者: 依然超级赛亚人    时间: 2014-8-7 21:32
陶圣虎 发表于 2014-8-7 16:17
这个是因为迭代器指针问题。指针第一次已经运行到迭代器的最末尾位置,当第二次循环再次询问是否有hasNext ...

高手!确实是这样。我忽略了这一点,以为上面第一个while遍历之后,指针会自动恢复成初始情况下的状态,看来指针是停在了最后一个元素上。
作者: 依然超级赛亚人    时间: 2014-8-7 21:34
rolling-stone 发表于 2014-8-7 16:43
迭代器本质上是指针,迭代的时候指针不段的向后判断,你第一个while已经将指针移到最后面了,第二个while再 ...

恩啊,问题就如大家所说,下面再接一个while遍历的话,相当于在第一个的基础上继续向后判断,此时确实已经没有元素可取。:handshake
作者: 陶圣虎    时间: 2014-8-7 21:34
依然超级赛亚人 发表于 2014-8-7 21:32
高手!确实是这样。我忽略了这一点,以为上面第一个while遍历之后,指针会自动恢复成初始情况下的状态, ...

:D我新手刚开始学呢  互相学习
作者: liqi    时间: 2014-8-7 21:47
学习了,谢谢楼主的问题和大家的解答
作者: 怀念黑海岸    时间: 2014-8-7 21:50
楼上的同学们说的很对呢:你第一次执行完while循环后it对象的指针已经知道最后了,所以你第二次再执行it.hasNext()肯定就没了。你可以在第一个while后面加一句System.out.println(it.hasNext());结果为false。
     如果你使用的是ListIterator的话那么你可以在第一次while结束后加上一个while反向迭代,
      ListIterator<Integer> it =list.listIterator();
      while(it.hasPrevious()){
                        System.out.print(it.previous());
这时候就可以再迭代一次。。
作者: 依然超级赛亚人    时间: 2014-8-8 06:43
怀念黑海岸 发表于 2014-8-7 21:50
楼上的同学们说的很对呢:你第一次执行完while循环后it对象的指针已经知道最后了,所以你第二次再执行it.ha ...

确实,我按照这个方式试了一下,结果打印了两次。第二次是逆向打印的,没想到出现的一个问题顺便把逆向遍历这个知识点也给体会了一下,呵呵。
作者: 依然超级赛亚人    时间: 2014-8-8 06:46
rolling-stone 发表于 2014-8-7 16:43
迭代器本质上是指针,迭代的时候指针不段的向后判断,你第一个while已经将指针移到最后面了,第二个while再 ...

开始我以为第一个while执行完毕后就恢复成原来的初始状态了,没有想到指针会呆在最后一个元素上,现在看来再写一个while是和原来的叠加了,所以没有元素可取了。:handshake
作者: 依然超级赛亚人    时间: 2014-8-8 06:47
icris 发表于 2014-8-7 16:49
第二个 while(it.hasNext()){} == while(false){}

回答的简单明了啊,程序在语义上确实是这么处理的。:handshake
作者: 依然超级赛亚人    时间: 2014-8-8 06:50
zz_job 发表于 2014-8-7 17:28
因为第一个迭代器的指针已经指向集合的末尾了,因此你的第二个while循环实际上判断条件始终为假,因为it.ha ...

恩啊,经过大家这么一说我才明白:第一个while判断之后没有恢复成它判断之前的状态,也就是指针没有自动回到第一个元素前面,再写while自然就不执行了。:handshake
作者: 依然超级赛亚人    时间: 2014-8-8 06:55
kakasa 发表于 2014-8-7 17:51
嗯 指针走弯了

简单易懂,明白!:handshake
作者: 依然超级赛亚人    时间: 2014-8-9 06:44
左脑想你 发表于 2014-8-7 18:20
每一个next指针都会向后一个第一个循环过后指针在最后的位置,第二个循环的条件判断是指针还是在最后也就是 ...

嗯啊,我就在这个点上不知是哪种情况,不知判断到最后结束时指针是停在最后一个元素上还是回到初始位置,之前理解为自动回到第一个元素的位置处,现在经过大家的提醒已经知道了科问题所在。:handshake
作者: 依然超级赛亚人    时间: 2014-8-9 06:47
王洪涛 发表于 2014-8-7 18:24
就像同步了一样

相当于第二个while和第一个while“连接”起来了,第一个while执行完毕后,后面没有元素了,第二个while也就不执行了,判断条件为false.
作者: 依然超级赛亚人    时间: 2014-8-9 07:36
继续悲伤 发表于 2014-8-7 20:50
你在第一次遍历完以后再添加元素试试!!

会发生ConcurrentModificationException(并发修改异常),因为这违反了“迭代器遍历,迭代器修改。集合遍历,集合修改”的原则,如果换成普通for或者增强for循环,然后用集合修改的话就失去了这道题原来的本质,想想是这样吗?:lol
作者: 依然超级赛亚人    时间: 2014-8-9 07:38
liqi 发表于 2014-8-7 21:47
学习了,谢谢楼主的问题和大家的解答

互相学习,互相借鉴,一起探讨,大家彼此都不用客气。:lol
作者: 左脑想你    时间: 2014-8-9 13:12
依然超级赛亚人 发表于 2014-8-9 06:44
嗯啊,我就在这个点上不知是哪种情况,不知判断到最后结束时指针是停在最后一个元素上还是回到初始位置, ...

兄弟你要是先进黑马了给我留个亲友券。。。。我现在还在传智上基础班
作者: 依然超级赛亚人    时间: 2014-8-9 13:29
本帖最后由 依然超级赛亚人 于 2014-8-9 13:32 编辑
左脑想你 发表于 2014-8-9 13:12
兄弟你要是先进黑马了给我留个亲友券。。。。我现在还在传智上基础班

弱弱的说一句,我在准备8月底的,7月末在传智基础班毕业...现在我才走基础测试这个程序,估计不少比我晚毕业的都能赶到我前面,自己学的有点渣...不过,果真我有幸比哥们你早进去的话,有亲友券的话...对了,我还不知能进黑马的人有几张亲友券呢,之前已经有个同班的也说过你相同的话,我答应了,到最后如果只有一张的话那我可就为难了。这样吧,假如只有一张而且你们俩到时都需要的话(也许你们在我之前就进去了),我还是给他吧,虽然拒绝人挺不好的,但我也不能食言于提前打过招呼的哥们儿,你说对吧?如果他用不到,我就给你,一言为定!
作者: 王洪涛    时间: 2014-8-9 18:05
依然超级赛亚人 发表于 2014-8-9 06:47
相当于第二个while和第一个while“连接”起来了,第一个while执行完毕后,后面没有元素了,第二个while也 ...

恩 因为遍历的时候List集合石油角标的 你while遍历第一遍的时候指针已经判断到尾了,Iterator有个子接口ListIterator 有个hasPrevious()方法可以到这再遍历一遍
作者: 依然超级赛亚人    时间: 2014-9-27 23:12
左脑想你 发表于 2014-8-9 13:12
兄弟你要是先进黑马了给我留个亲友券。。。。我现在还在传智上基础班

哥们,虽然感觉现在很晚,估计你都被黑马录取很久了,但是为了践行当初的诺言,我还是想问一下,你是不是已经被录取了?还用亲友券吗?我现在有一张亲友券。我报的46期,29号才能下来成绩,所以之前也没有可用的亲友券给你,有点惭愧,要是用得到的话就招呼一声。
作者: WJN_YES    时间: 2014-9-29 10:11
因为迭代器里包含指针,当第一个循环while(it.hasNext())判断下一点是否有数据,然后打印it.next的时候指针就会往后移动一次,知道循环结束时指针就到了结尾,这样下一个循环while(it.hasNext())中it.hasNext()的返回值是false,因此不会进行第二个while循环
作者: 左脑想你    时间: 2014-10-8 22:15
依然超级赛亚人 发表于 2014-9-27 23:12
哥们,虽然感觉现在很晚,估计你都被黑马录取很久了,但是为了践行当初的诺言,我还是想问一下,你是不是 ...

谢啦。。。我已经不用了我上了45期
作者: 依然超级赛亚人    时间: 2014-10-8 23:13
左脑想你 发表于 2014-10-8 22:15
谢啦。。。我已经不用了我上了45期

恩啊,已经上了就好,加油吧,有些晚了,不太好意思,我上了46期...




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