为什么迭代器没有重置方法?

36

为什么?最佳方法是将迭代器项指针移动到第一个位置吗?

5个回答

38

为什么要这样做?

因为如果你强制迭代器拥有一个重置(reset)方法,那么每个迭代器都必须拥有一个重置方法。这会给每个迭代器的编写者增加额外的工作量。此外,有些迭代器非常难(或非常昂贵)重置,而你不希望用户对它们调用重置方法。文件或流迭代器是很好的例子。

将迭代器指针移动到第一个位置的最佳方法是什么?

创建一个新的迭代器。这通常比重置操作更少开销。


6
(除了有一个“remove”方法外,它实际上并没有给所有迭代器“额外的工作”,因为该操作是可选的。) - aioobe
@aioobe 在一些场景下,通过迭代器删除当前对象对于开发者来说是非常方便的。而重置则很少有这种情况(因为你几乎总可以创建一个新的迭代器)。 - DJClayworth
2
@DJClayworth “这会给每个迭代器编写者带来额外的工作。” 这不是一个合理的回应。库实现者需要付出一点额外的努力,但回报是许多库用户将受益。 - stackoverflowuser2010
2
更重要的一点是第二个,即有些迭代器无法重置。 - DJClayworth
1
如果一个迭代器是一个方法参数,那该怎么办呢?如果我想要对迭代器所做的更改能够传递给方法调用者... 我就无法做到了,对吧? - Campa

6

一旦你读取了一个流,如果不重新打开源文件,就无法重新读取它。这就是流和迭代器的工作原理。


3
最好的方法是创建一个新的!

1
你可以按照之前的方式创建迭代器:Iterator<T> iterator = iterable.iterator(); - Jean Logeart

3

在JCF中采用了一种普遍的趋势 - 保持接口极简,除非这使得某些特性的使用变得极其困难。 这就是为什么您没有针对像不可变集合、固定大小集合等语义的单独接口的原因。

至于为什么提供了remove(Object)(作为可选项)- 不提供此功能将使在迭代集合时安全地删除项目变得不可能 - 没有任何东西使提供reset()如此必要。

同样地,为什么还有一个单独的ListIterator()(提供像previous()previousIndex()之类的方法) - 对于List接口,在使用时主要的功能是能够根据索引布局元素,并且能够按索引顺序访问它们,无论是固定顺序还是随机顺序。 这在其他集合中并不适用。如果不为List提供此接口,将使使用列表变得非常困难,甚至不可能。


几乎任何IteratableIterator都可以执行一些有用的操作,这些操作本应该包含在接口中,但实际上并没有。有用的迭代器方法包括skip [相当于N个连续的移动调用,尽管许多迭代器可以在O(1)时间内实现它]和copyLocation [它将返回一个预期产生与原始迭代器相同项的迭代器]。任何迭代器都可以实现skip方法,而任何非巨大有限迭代器都可以通过枚举自身到数组中来实现copyLocation,然后同时具有它和副本... - supercat
返回数组中的项目。客户端代码可以自行执行任一操作,但如果迭代器对其内部工作有特殊了解而客户端代码缺乏此类知识,则可以利用这种知识提供多个数量级的速度改进。 - supercat

2

提示:将您的迭代变量作为函数创建,然后可以多次使用它。这仅适用于基础逻辑可重复的情况。

在Scala中的示例(Java类似但我没有一个Java REPL手头)

def i = (1 to 100) iterator   // i is our iterator
i.grouped(50) foreach println // prints two groups
i.grouped(50) foreach println // prints same two groups again

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接