大家先来看段代码吧:
List list = new ArrayList();
list.add("exception");
for (Iterator iter = list.iterator(); iter.hasNext();) {
String element = (String) iter.next();
list.remove(element);
}
这段代码运行时会抛出异常,呵呵,不知道大家发现问题没?
这段代码会抛出:java.util.ConcurrentModificationException。也就是所谓的“Fail Fast”。用了很久Java了,才发现这么一个异常,着实郁闷了一把......啥都不说了,拿起书来,重新来过。
为什么要Iterator?
下面是一个Collection的总体图:
上面代码涉及了一个经典的涉及模式-Iterator模式。既然涉及了这个模式,就要问问为什么这里要用这个模式。查了一下书,有这么几句描述Iterator的:迭代逻辑没有改变,但是需要将一种聚集变换成另一种聚集。因为不同的聚集遍历接口不同,所以需要修改客户端代码。这几句话没错,而且我们用Iterator都有如文章开头示例的标准方式,然而仔细想来却还有点问题。
假设Iterator是为了实现遍历方便。可是,我们几个常用的聚集(如:ArrayList,LinkedList,Set等)都已经间接实现了Collection接口。而大家应该注意到Collection接口中有个size()方法。这样的结果是,对所有实现了Collection的聚集而言,我们都可以通过for (int i = 0; i < list.size(); i++)这样的形式实现遍历。而且,JDK1.5还可以通过foreach的形式大大简化代码量。所以,这样想来Iterator为了实现遍历的方便而引入,显然不成立。
接着找找。我们可以注意到,Set和List两个大类中一个很大的区别是:List提供get方法,而Set没有提供get方法。这样的结果是Set类只能往集合中放,却不能从集合中取(从一般的常识来说,这样做还是合理的)。呵呵,所以这里我只能猜想Iterator是不是是为了访问Set中元素而设计的了。
仅仅猜想,不知道大家有没有什么更好的想法?
讨论:
跟朋友讨论了一下,for(int i = 0; i < list.size(); i++)对应遍历LinkedList来说是致命的。对ArrayList是O(n),而LinkedList则是O(n^2),这样的效率是不能让人接受的。
如上所说,那么foreach的引入应该是在编译层次对两种不同数据结构进行了不同处理。而且成为了Iterator的替代。
不过这里又引出了另一个问题——
Iterator模式如何用在其他地方?作为一种设计模式Iterator应该有更广的使用价值吧~
Iterator的缺点
- 聚集中的元素有些是有顺序的,而有些是没有顺序可言的。使用过度Iterator会产生一种元素顺序的误解。
- Iterator给出的元素没有类型。这点很致命啊。而且也是JDK1.5一大优势。
- Iterator使得某些同步的类在使用了Iterator后,成为不同步(不能说不同步,只是Iterator无法并发)。如Vector。
这里没有贬低Iterator的意思,只是实在看不出他有啥好处......
集合
能力有限,感觉了解还是太少,也没太多好说的,只是有些区别应该注意一下。
- 继承List的几个类中,只有Vector是同步的。当然也包括Vector的子类Stack。
- 如果需要对不同步的List,Set等可以考虑使用Collections类中的方法。
posted on 2006-11-19 21:32
KeepRunning 阅读(299)
评论(0) 编辑 收藏 所属分类:
Java点滴