noa*_*mtm 20 java iterator iterable
我读了为什么Java的迭代器不是Iterable?而为什么不枚举可迭代?,但我仍然不明白为什么这样:
void foo(Iterator<X> it) {
for (X x : it) {
bar(x);
baz(x);
}
}
Run Code Online (Sandbox Code Playgroud)
没有成功.换句话说,除非我遗漏了某些东西,否则上面可能是一个很好的有效语法糖:
void foo(Iterator<X> it) {
for (X x; it.hasNext();) {
x = it.next();
bar(x);
baz(x);
}
}
Run Code Online (Sandbox Code Playgroud)
Mic*_*yan 19
最有可能的原因是因为迭代器不可重复使用; 每次想要迭代元素时,你需要从Iterable集合中获得一个新的Iterator.但是,作为快速修复:
private static <T> Iterable<T> iterable(final Iterator<T> it){
return new Iterable<T>(){ public Iterator<T> iterator(){ return it; } };
}
//....
{
// ...
// Now we can use:
for ( X x : iterable(it) ){
// do something with x
}
// ...
}
//....
Run Code Online (Sandbox Code Playgroud)
也就是说,最好的办法就是简单地绕过Iterable<T>界面而不是Iterator<T>
但我仍然不明白为什么这个[...]不可能实现.
我可以看到几个原因:
Iterators不是可重用的,所以for/each会消耗迭代器 - 也许不是不正确的行为,但对那些不知道for/each如何被去除的人来说是不直观的.Iterators在代码中看起来并不是"赤裸裸",因此它会使JLS变得很复杂而且收益很小(for/each结构很糟糕,因为它在Iterables和数组上工作).Iterables实用程序类中包含此解决方法,类似于Collections和Arrays,但是,在我之外.)java.lang[来源请求],所以他们不得不创建一个Iterator接口java.lang,其java.util.Iterator扩展无需增加任何东西.现在我们有两个功能相当的迭代器接口.使用裸迭代器的新代码的50%将选择java.lang版本,其余使用中的一个java.util.混乱随之而来,兼容性问题比比皆是等等.我认为第1-3点与Java语言设计理念似乎非常一致:不要让新手感到惊讶,如果它没有明显的收益来掩盖成本,请不要使规范复杂化,并且不要使用语言功能可以使用库来完成.
同样的论点也可以解释为什么java.util.Enumeration不是Iterable.
该for(Type t : iterable)语法仅适用于实现类Iterable<Type>.
迭代器不实现iterable.
您可以通过类似的事情重复Collection<T>,List<T>或者Set<T>是因为他们实现Iterable.
以下代码是等效的:
for (Type t: list) {
// do something with t
}
Run Code Online (Sandbox Code Playgroud)
和
Iterator<Type> iter = list.iterator();
while (iter.hasNext()) {
t = iter.next();
// do something with t
}
Run Code Online (Sandbox Code Playgroud)
这是不可能的原因,是因为for-each语法被添加到语言中以抽象出来Iterator.使for-each循环与迭代器一起工作将无法实现for-each循环的创建.
事实上,你可以。
java 8 上有很短的解决方法:
for (X item : (Iterable<X>) () -> iterator)
Run Code Online (Sandbox Code Playgroud)
有关该技巧的详细说明,请参阅如何在 java 8 流上使用 foreach 循环进行迭代。
在相关问题中可以找到一些解释为什么这不被本地支持:
为什么 Stream<T> 没有实现 Iterable<T>?
| 归档时间: |
|
| 查看次数: |
19666 次 |
| 最近记录: |