【发布时间】:2012-06-28 08:11:17
【问题描述】:
可能重复:
Why is Java's Iterator not an Iterable?Idiomatic way to use for-each loop given an iterator?
Can we use for-each loop for iterating the objects of Iterator type?
据我所知,foreach 循环是 Java 5 中添加的语法糖。所以
Iterable<O> iterable;
for(O o : iterable) {
// Do something
}
基本上会产生与
相同的字节码Iterable<O> iterable;
for(Iterator<O> iter = iterable.iterator(); iter.hasNext(); /* NOOP */) {
O o = iter.next();
// Do something
}
但是,如果我一开始没有可迭代对象,而只有一个迭代器(比如说,因为一个类提供了两个不同的迭代器),我就不能使用语法糖 foreach 循环。显然我仍然可以进行简单的旧样式迭代。但是,我实际上想做:
Iterator<O> iter;
for(O o : iter /* Iterator<O>, not Iterable<O>! */) {
// Do something
}
当然我可以做一个假的Iterable:
class Adapter<O> implements Iterable<O> {
Iterator<O> iter;
public Adapter(Iterator<O> iter) {
this.iter = iter;
}
@Override
public Iterator<O> iterator() {
return iter;
}
}
(这实际上是对 Iterable API 的丑陋滥用,因为它只能迭代一次!)
如果它是围绕 Iterator 而不是可迭代设计的,可以做很多有趣的事情:
for(O o : iterable.iterator()) {} // Iterate over Iterable and Collections
for(O o : list.backwardsIterator()) {} // Or backwards
Iterator<O> iter;
for(O o : iter) {
if (o.something()) { iter.remove(); }
if (o.something()) { break; }
}
for(O : iter) { } // Do something with the remaining elements only.
有人知道为什么语言是这样设计的吗?如果一个类同时实现Iterator 和Iterable,为了避免歧义?为了避免假定“for(O o : iter)”将处理所有元素两次(并且忘记获取新的迭代器)的程序员错误?还是有其他原因?
还是有一些我不知道的语言技巧?
【问题讨论】:
-
或this one。
-
两者都很接近,但并不完全相同。迭代器不应该是可迭代的,因为您只能迭代一次(没有“重新启动”)。而且我知道你不能在迭代器上使用 foreach(除非你使用我概述的适配器),但我试图理解为什么 Java 是这样设计的。
-
咩;我倾向于不同意。 1.5 文档中给出的答案只是表明设计人员选择这种方式来处理最常见的用例。有时答案是“只是因为”。
-
有时设计师有理由以一种或另一种方式设计语言......试图理解他们的推理有什么问题(即使我无法改变事情)?
-
谁说试图理解他们的推理有什么问题?我说是他们决定去抓低垂的果实,他们就是这样做的,不一定有太多要理解的。
标签: java syntax iterator language-design iterable