Java Iterables 使用每个 Foreach 构造“重置”迭代器
Posted
技术标签:
【中文标题】Java Iterables 使用每个 Foreach 构造“重置”迭代器【英文标题】:Java Iterables "Resetting" Iterator With Every Foreach Construct 【发布时间】:2012-12-08 14:39:00 【问题描述】:我相信我已经注意到,对于某些 Iterables(例如 IterableString class),要么创建了一个新的迭代器,要么迭代器以某种方式在每个新的 foreach 构造中重新开始,但这似乎不会发生在其他可迭代...
例如,如果您运行以下代码:
import java.util.ArrayList;
public class test
public static void main(String args[])
IterableString x = new IterableString("ONCE");
System.out.println("***");
for (char ch : x)
System.out.println(ch);
System.out.println("***");
for (char ch : x)
System.out.println(ch);
ArrayList y = new ArrayList();
y.add('T');
y.add('W');
y.add('I');
y.add('C');
y.add('E');
System.out.println("***");
for (char ch : y)
System.out.println(ch);
System.out.println("***");
for (char ch : y)
System.out.println(ch);
System.out.println();
您将看到以下输出:
***
O
N
C
E
***
***
T
W
I
C
E
***
T
W
I
C
E
带有 x 的第二个 foreach 循环似乎从它停止的地方开始(在最后一项之后),但是带有 y 的第二个 foreach 循环似乎从它第一次开始的地方开始(在第一项)。为什么会这样?我们如何才能让 Iterables 表现得像后者(ArrayLists)?
更具体地说,我们将如何修改像 IterableString 这样的类以像 ArrayList 一样工作?
【问题讨论】:
IterableString
到底是什么??该未知对象可能与迭代器的配置方式有关...
Iterable
的 Javadoc 似乎并没有说太多,以便强制每次调用 iterator()
返回一个新的 Iterator
- 但这似乎是 JDK 接受的做法(和明智的)。所以它看起来像一个“错误”,由谁创建了IterableString
。
【参考方案1】:
ArrayList
能够在 java foreach 循环中被迭代,因为它在 Java 中实现了 Iterable
接口。 Iterable
接口概述了一个方法iterator
,它返回集合的迭代器。在 Java 中使用 foreach 循环在后台使用此方法的迭代器。每次创建新的 foreach 循环时,ArrayList
都会提供一个新的迭代器。
如果你想创建一个可以在 Java 中使用 foreach 循环进行迭代的类,你需要实现 Iterable
接口并定义如何迭代集合。
【讨论】:
这仍然没有解决 OP 的问题 我对@Code-Guru 的评论感到有些困惑。也许我误解了这个问题,但我概述了为什么 ArrayList 在 foreach 循环中有这种行为以及如何在用户定义的类中模仿它。 问题是为什么IterableString
类的行为与ArrayList
不同。【参考方案2】:
IterableString
类(由您的linked article 定义)既是Iterable
,又是Iterator
。这是否是一个好主意值得商榷 - 但一个简单的解决方法是:
// This method implements Iterable.
public Iterator<Character> iterator()
return new IterableString(this.str);
【讨论】:
谢谢!我被我在其他可迭代对象中看到的类似问题所困扰(例如this one,其中嵌套迭代器类有另一个问题,它需要考虑到它对更改其外部类中的组件具有状态意识)。出于某种原因,错误的表面上的一致性给我的印象是,像 ArrayList 这样的可迭代对象发生了一些特殊的事情,而不是我正在查看的非标准可迭代对象中的碎片。以上是关于Java Iterables 使用每个 Foreach 构造“重置”迭代器的主要内容,如果未能解决你的问题,请参考以下文章