Iterator模式

JAVA COLLECTION类都提供Iterator模式来迭代的取数据,比如ArrayList最终实现Iterable接口,但是
(一)
for(int i=0,i<size;i++){
a.get(i);
......
}

(二)
Iterator i = a.inerator();
while(i.hasNext()){
......
}

1和2都能遍历list实例a的所有元素,没看出用iterator有什么优势。

起先我的想法就是Iterator提供了List的一个不可变视图,如果你想把List发布给一个方法查看而又不希望这个方法能修改它,则发给给该方法一个List的不可更改视图,但是这个想法有几个问题:
(1)Iterator并非不可改,有remove方法
(2)如果是发布不可变试图的话完全可以用Collections.unmodifyList(a);
(3)如果仅仅是发布不可变视图的话也未必要是Iterator这个形式,试想一下,一个方法的参数是Iterator将是多么晦涩难理解的,我也没见过这个用的。

我的第二个想法是Iterable接口是所有Collection对象都必实现的,也许在List里体现不出优势,在其他集合类里能体现出来,List实现Iterable只是List作为集合类所顺理成章实现的。

到底Iterator的优势在哪里

iterator可以向前 向后遍历,是一个指针对象,完全可以用指针来想象它。

iterator借助泛型可以是任何对象,它是一个完全对象式的表达方式,而array是非对象化的,一般不推荐使用。

Iterable接口是所有Collection对象都必实现的,是一个通用功能,这易于编程,否则N时间不用后,我还要想想不同collection该用不同的遍历方式,太麻烦了。这本身就是优点。

了解

Some clues:
if implements Iterable interface, you can use ***.iterator to get an Iterator.

Isn't that beautiful? A little framework....

为什么使用iterator,就是因为用***.iterator 来隐藏***的内部实现。

感觉Iterator模式有点像adaptor模式的特例,本质上还是修改访问接口吧?

不知道我这么理解对不对?

比较像Adapter,应该算是将内部行为委派成另一种形式,和Map.keySet()类 似

用iterator是不是增加了一个对象,这不是又增加了不必要的开销吗?
实现iterator接口的遍历比for循环遍历能带来更优化的方案吗?
请高人指点
[该贴被zhongwenly于2008-12-19 15:26修改过]
[该贴被zhongwenly于2008-12-19 15:45修改过]

BAQN:
iterator可以向前 向后遍历,是一个指针对象,完全可以用指针来想象它。
iterator借助泛型可以是任何对象,它是一个完全对象式的表达方式,而array是非对象化的,一般不推荐使用。
Iterable接口是所有Collection对象都必实现的,是一个通用功能,这易于编程,否则N时间不用后,我还要想想不同collection该用不同的遍历方式,太麻烦了。这本身就是优点。

其实BANQ已经说的很清楚了!你从对象的角度来考虑。ITERATOR是可以重复使用的遍历。

用iterator是不是增加了一个对象,这不是又增加了不必要的开销吗?实现iterator接口的遍历比for循环遍历能带来更优化的方案吗?
其实你使用JAVA你可以将重点放在对象的优化上面!而不必追溯FOR循环和ITERATOR接口的优化比较。

没有真正 接触过

看看A和B哪个实现更好?


interface E{
public void do0();
public void do1();
public void do2();
//...
public void doN();
}

class A{
public void doSomething(Collection<E> c){
for(Iterator<E> i = c.iterator();i.hasNext();){
i.next().do0();
}
}
}

class B{

public void doSomething(List<E> c){
for(int i=0;i<c.size();i++){
c.get(i).do0();
}
}

public void doSomething(Set<E> c){
for(Iterator<E> i = c.iterator();i.hasNext();){
i.next().do0();
}
}
}

假设编写完成后 需求改了,我要在遍历的时候加入do1(),那么A只要改一处,而B要修改两处。

再假设,需求又改了,我又要加入do2(),那么A还是要改一处,B还是要改两处。

依次类推,需求改了N次,那么A一共改了N次,B却要改动2N次。

如果程序中用到的Collection接口的实现类有M个。那么为应对N次的需求修改,A的代价还是N次,而B则要M*N次。

至此Iterator的好处不言而喻。记得Gof那本书里讲过。
使用Iterator的关键,是把所有Collection的遍历定义了统一的接口,使用起来不必关心具体的遍历是如何实现的(不管List,Set,还是什么其他的),只要拿来用就可以了,因为在大多数情况下,我们都只是需要把每个元素拿出来,然后对元素进行操作就可以了。

举个例子,假如我有一个实现Collection接口的二叉树类,你可以对该二叉树进行“先序遍历”“中序遍历”或“后序遍历”,那我只要在二叉树类中实现些遍历,然后通过Iterator接口返回给你,而不管是哪种遍历,你的用法永远都是同一个样子:


for(Iterator<E> i = c.iterator();i.hasNext();){
i.next().do0();
}

你根本不必知道什么是“先序遍历”“中序遍历”“后序遍历”、。。。。“乱七八糟遍历”

这就像躲在窗口里边的售票员,她只负责喊:“下一个”,然后收钱卖票。她不会理会买票的人是排队的,还是夹塞的。

---------------------------------------------------------

另外:size()本身有最大值的缺陷。

api doc:

size

int size()

Returns the number of elements in this list. If this list contains more than Integer.MAX_VALUE elements, returns Integer.MAX_VALUE.

Specified by:
size in interface Collection<E>

Returns:
the number of elements in this list


[该贴被darasion于2008-12-22 15:29修改过]
[该贴被darasion于2008-12-22 15:32修改过]
[该贴被darasion于2008-12-22 16:03修改过]

高阿,学到了。。谢谢