Iterator模式

08-09-16 bloodrate
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的优势在哪里

banq
2008-09-17 08:29
iterator可以向前 向后遍历,是一个指针对象,完全可以用指针来想象它。

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

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

ITfuture
2008-09-17 10:37
了解

vodomore
2008-09-18 07:16
Some clues:

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

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

fox0424
2008-09-18 12:58
为什么使用iterator,就是因为用***.iterator 来隐藏***的内部实现。

tainy
2008-09-19 10:31
感觉Iterator模式有点像adaptor模式的特例,本质上还是修改访问接口吧?

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

bloodrate
2008-09-19 12:00
比较像Adapter,应该算是将内部行为委派成另一种形式,和Map.keySet()类 似

zhongwenly
2008-12-19 15:25
用iterator是不是增加了一个对象,这不是又增加了不必要的开销吗?

实现iterator接口的遍历比for循环遍历能带来更优化的方案吗?

请高人指点

[该贴被zhongwenly于2008-12-19 15:26修改过]

[该贴被zhongwenly于2008-12-19 15:45修改过]

ITfuture
2008-12-20 12:55
BAQN:

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

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

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

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

用iterator是不是增加了一个对象,这不是又增加了不必要的开销吗?实现iterator接口的遍历比for循环遍历能带来更优化的方案吗?

其实你使用JAVA你可以将重点放在对象的优化上面!而不必追溯FOR循环和ITERATOR接口的优化比较。

dnydoney
2008-12-20 13:44
没有真正 接触过

darasion
2008-12-22 15:10
看看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();
		}
	}
}
<p>

假设编写完成后 需求改了,我要在遍历的时候加入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();
}
<p>

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

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

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

另外: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修改过]

dill
2009-06-13 22:08
高阿,学到了。。谢谢

猜你喜欢