【问题标题】:When implementing the Iterable interface, shouldn't the iterator() method return a clone of the collection?在实现 Iterable 接口时, iterator() 方法不应该返回集合的克隆吗?
【发布时间】:2015-12-09 06:07:46
【问题描述】:

我已经看到很多关于如何实现 Iterable 接口的示例,其中 iterator() 方法仅返回要迭代的原始集合。但这似乎违背了迭代器的部分目的,因为它应该能够迭代所述集合而不用担心集合在你下面的变化。 Iterable 的 iterator() 方法不应该总是返回集合的克隆吗?而且,最好是深度克隆?

我知道,这个问题的答案可能部分基于意见,这是禁止的。但是,我想要了解的是 Iterable 接口的初衷,而不是人们可能决定或未决定使用它的目的。

【问题讨论】:

  • 我认为这取决于集合的实现。
  • 这取决于,一般来说,大多数Collection(s) AFAIK 出于这个原因使用快速失败Iterator
  • 这绝对不是Iterable接口的原始实现。这将使您在迭代时绝对不可能更改集合元素,这完全是一件有用的事情。
  • 有些集合可以(在某种程度上)按照您的建议进行。用于CopyOnWriteArrayListIterator 在构造Iterator 时包含对支持Object[] 的引用。在迭代过程中对List 的任何写入都会创建一个全新的数组。

标签: java iterator


【解决方案1】:

但这似乎违背了迭代器的部分目的,因为它应该能够迭代所述集合,而不必担心你下面的集合会发生变化。

这不是迭代器给你的保证之一。实际上,创建了一个特殊的异常ConcurrentModificationException,目的是提醒程序员注意他正在迭代的集合在他下面被修改的情况。

Iterable 的 iterator() 方法不应该总是返回集合的克隆吗?而且,最好是深度克隆?

绝对可以。然而,这将非常昂贵,尤其是对于如此基础的操作。想一想:每次您希望对集合运行 for-each 循环时,库都会“哦,等一下,我必须克隆整个 1000 个元素的东西,然后再让您进行迭代”。这会非常慢,并且会提示程序员在他们认为性能很关键的情况下停止使用迭代器(这包括很多性能实际上并不关键的情况)。

最重要的是,Java 不知道如何克隆您的元素,即使您实现了Cloneable(因为Cloneable is broken)。

当然,您始终可以选择自己克隆一个集合,并对其进行迭代以更好地隔离并发运行的进程。然而,在这种情况下,程序员需要做出为这种隔离买单的决定,这与库为他做出这个决定是不同的。

【讨论】:

  • 谢谢。三个小时的挖掘让我一无所获。您在 2 分钟内回答了我的问题。
猜你喜欢
  • 2013-10-05
  • 1970-01-01
  • 1970-01-01
  • 2017-08-18
  • 2015-12-13
  • 2023-03-15
  • 2020-01-24
  • 1970-01-01
  • 2014-12-19
相关资源
最近更新 更多