黑马程序员技术交流社区

标题: 关于迭代器的疑问 [打印本页]

作者: 〃Mr.Zぐ    时间: 2013-6-5 00:41
标题: 关于迭代器的疑问
List特殊之处是可以通过listIterator方法返回一个ListIterator对象,
即一个迭代器,而List下面有很多实现类和接口,当类实例化后,
ArrayList  al  =  new  ArrayList(),是否都可以创建ListIterator对象?
ListIterator  li   =   al.listIterator()?然后在迭代过程中,
只能用迭代器中的方法,但为什么不能同时用两个?
while(li.hasNext()){if(li.next().equals("java")) li.add("java2");
li.remove("java3")}add和remove同时用会报异常?
作者: a303466738    时间: 2013-6-5 03:21
{:soso_e121:}第一次回答问题,答的不好不要喷,不全面望指导~~~
首先回答你的第一个问题:List下面有很多实现类和接口,当类实例化后,ArrayList  al  =  new  ArrayList(),是否都可以创建ListIterator对象?

答案是可以的,因为实例化的都是List的子类,可以调用父类的方法,这是继承。而List通过子类来实例化,这是多态中的接口的引用指向具体实现类的对象。
你可以多去看看面向对象的视频,面向对象的三大特性:封装,继承,多态。这里就不会有问题了。

再说第2个问题:while(li.hasNext()){if(li.next().equals("java")) li.add("java2");li.remove("java3")}add和remove同时用会报异常?

你报异常是因为用错了方法,你可以看下API中的remove说明:void remove()
从迭代器指向的 collection 中移除迭代器返回的最后一个元素(可选操作)。每次调用 next 只能调用一次此方法。如果进行迭代时用调用此方法之外的其他方式修改了该迭代器所指向的 collection,则迭代器的行为是不确定的。
也就是说,remove()方法中是不可以传参数的。
因为Iterator 是工作在一个独立的线程中,并且拥有一个 mutex 锁。 Iterator 被创建之后会建立一个指向原来对象的单链索引表,当原来的对象数量发生变化时,这个索引表的内容不会同步改变,所以当索引指针往后移动的时候就找不到要迭代的对象,所以 Iterator 在工作的时候是不允许被迭代的对象被改变的。
但你可以使用 ListIterator 本身的方法 remove() 来删除对象,li.remove() 方法会在删除当前迭代对象的同时维护索引的一致性。
所以你可以这样写:
        while(li.hasNext()){
                if(li.next().equals("java"))
                        li.remove();
                        li.add("java2");
        }
直白点说就是:你在用迭代器的时候,当迭代指向哪个对象的时候,你才可以对哪个对象操作。
作者: yp324    时间: 2013-6-5 08:19
List和Set都有iterator()来取得其迭代器。对List来说,你也可以通过listIterator()取得其迭代器,两种迭代器在有些时候是不能通用的,Iterator和ListIterator主要区别在以下方面:
1. ListIterator有add()方法,可以向List中添加对象,而Iterator不能
2. ListIterator和Iterator都有hasNext()和next()方法,可以实现顺序向后遍历,但是ListIterator有hasPrevious()和previous()方法,可以实现逆向(顺序向前)遍历。Iterator就不可以。
3. ListIterator可以定位当前的索引位置,nextIndex()和previousIndex()可以实现。Iterator没有此功能。
4. 都可实现删除对象,但是ListIterator可以实现对象的修改,set()方法可以实现。Iierator仅能遍历,不能修改。 因为ListIterator的这些功能,可以实现对LinkedList等List数据结构的操作。
其实,数组对象也可以用迭代器来实现。 org.apache.commons.collections.iterators.ArrayIterator就可以实现此功能。
一般情况下,我们使用Iterator就可以了,如果你需要进行记录的前后反复检索的话,你就可以使用ListIterator来扩展你的功能,(有点象JDBC中的滚动结果集)。
ListIterator是一个双向迭代器。ListIterator没有当前元素,它的当前游标是位于调用next()和previsous()返回的元素之间。不过下面举的例子有点问题:下面的例子是n+1个元素。如果有n个元素,那么游标索引就是0...n共n+1个。
注意:romove和set方法不是针对当前游标的操作,而是针对最后一次的next()或者previous()调用
作者: luckwei    时间: 2013-6-5 08:26
ListIterator是集合List的特有的迭代器接口,当List的子类实现或者继承List后当让也就有了list特有的迭代器ListIterator,实例对象后当让可以创建ListIterator的对象了啊。
你说的同时add和remove是在使用Iterator接口迭代时会发生的并发修改异常,那是因为add是集合中的方法,remove是Iterator迭代器的方法,同时用就可能方法异常。ListIterator 继承Iterator ,add,remove等方法都是迭代器的,所以添加删除都是ListIterator的,同时使用就不会有问题了
作者: 桉树    时间: 2013-6-5 08:46
listIterator 中的void remove():
从列表中移除由 next 或 previous 返回的最后一个元素(可选操作)。对于每个 next 或 previous 调用,只能执行一次此调用。只有在最后一次调用 next 或 previous 之后,尚未调用 ListIterator.add 时才可以执行该调用
作者: 袁梦希    时间: 2013-6-5 11:46
楼主好棒啊
作者: 袁梦希    时间: 2013-6-12 18:42
楼主你好  如果问题已经解决  请把帖子的类型改为已解决  然后会给你发几个粽子吃




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