【问题标题】:Can iterator.next() remove elements from the source? (Java)iterator.next() 可以从源中删除元素吗? (爪哇)
【发布时间】:2016-07-14 09:30:26
【问题描述】:

有一个Java函数

public <T> void batchWrite(Iterable<T> source, int number)

以省时的方式写入大量项目。

我想在ConcurrentLinkedQueue 上使用这个batchWrite(),它可以在batchWrite() 工作时写入。我希望batchWrite() 删除它从队列中取出的项目。

我可以编写一个迭代器(并将其包装成一个Iterable)来删除返回的项目:

class IteratorThatRemovesReturnedValues<T> implements Iterator<T> {
    Queue<T> queue;
    IteratorThatRemovesReturnedValues(Queue<T> q) { queue = q; }
    boolean hasNext() { return queue.peek() != null; }
    T next() { return queue.poll(); }
}

问题是:这不是滥用这个概念吗?

remove() 的描述说: 如果在迭代过程中底层集合被修改,迭代器的行为是不确定的。 这可以通过任何一种方式读取:Iterator 的特定实现可能被允许或不允许定义当以某种特定方式修改底层免等待队列时会发生什么。

从底层队列中移除返回的元素会与迭代器的约定相矛盾吗?

(替代方法是将poll() 的数量项放入辅助ArrayList 并在该列表上调用batchWrite()。)

编辑这个问题的另一面:迭代器可以由管道支持吗?

【问题讨论】:

  • IMO 你可以用 LinkedList 做同样的事情,而不用实现 Iterator 返回已删除的项目...
  • 是的,它会被滥用。迭代器的 next() 方法不应该被移除。为什么不直接使用队列的迭代器并调用 remove() 呢?
  • 我会说完全兼容的迭代器在不调用 remove 时不应该删除元素。想象一下,你为同一个集合创建了两个迭代器,并且想要对它们进行迭代; 繁荣。合同的问题是您可以期待某些行为。如果您的迭代器真的被称为IteratorThatRemovesReturnedValues,并且您以每个人都知道会发生什么的方式记录它的行为,那么我不会担心官方的预期合同。

标签: java iterator


【解决方案1】:

假设您没有考虑Iterator#remove() 方法的(许多)警告,根据合同,迭代器的行为很简单。特别是,它没有说明底层实现。

附注:从历史上看,IteratorCollection 上的迭代相关联,但这可能只是对遗留 Enumeration 类的补救措施。有许多Iterator 实现与集合相关。 (例如,Scanner 等等)。如今,Iterator 通常实际上只不过是一个“允许您查询是否有更多可用的东西的抽象源”

但严格来说,您的实现已经遵守合同。 Iterator#next() method 的文档说:

投掷:

NoSuchElementException - 如果迭代没有更多元素

这不是你的情况。您的实现将在此处简单地返回 null。当然,这可以通过将 poll() 调用替换为对 remove() 的调用来轻松缓解,这会方便地抛出 NoSuchElementException,但我想这会与您当前的目标相矛盾。

我认为关键在于您对next() 方法的实现具有对外界可见的副作用。 cmets 中已经给出了一个示例:当您创建其中两个迭代器实例时,它们的行为可能会按照它们的约定进行,但两者的行为可能与预期的不同。

后者仅指单线程使用。当两个线程独立地使用这些迭代器时,对hasNext()next() 的调用的交织可能会导致竞争条件。 (当两个线程使用单个迭代器时更是如此,但对于 all 迭代器就是这种情况,因为它们通常是有状态的)。


底线是:虽然预期使用的一些细节仍然不清楚(特别是关于迭代器在batchWrite方法中的使用方式,以及多个线程应该如何交互的问题),这种实现方式迟早可能会崩溃,并且错误将难以检测和重现。我建议在这里考虑替代实现。

【讨论】:

    猜你喜欢
    • 2020-06-05
    • 2012-10-18
    • 1970-01-01
    • 1970-01-01
    • 2017-08-27
    • 1970-01-01
    • 2020-07-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多