有一个Java函数
public <T> void batchWrite(Iterable<T> source, int number)
以节省时间的方式编写大量项目。
我想在batchWrite()
上使用此ConcurrentLinkedQueue
,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()
问题是: 不会滥用这个概念吗?
remove()
的说明:
如果在迭代进行过程中以除了调用此(Iterator
)方法之外的任何方式修改基础集合时,未指定迭代器的行为。
这可以通过以下任一方式读取:可以允许或不允许poll()
的特定实现来定义在以某种特定方式修改基础等待队列时发生的情况。
从基础队列中删除返回的元素是否与迭代器的契约相矛盾?
(另一种方法是ArrayList
将一定数量的项目放入辅助batchWrite()
并在该列表上调用declare namespace foo {
export function bar();
}
declare var baz: { some: number };
。)
编辑问题的另一面: 迭代器可以由管道支持吗?
答案 0 :(得分:1)
假设您没有考虑Iterator#remove()
方法的(许多)警告,根据合同,迭代器的行为很简单。特别是,它没有说明底层实现。
附注:从历史上看,Iterator
与Collection
上的迭代相关联,但这可能只是遗留Enumeration
类的补救措施。有很多Iterator
个实现不与集合相关。 (例如,Scanner
等等)。如今,Iterator
通常不仅仅是一个&#34;抽象的事物来源,它可以让您查询是否有更多可用的东西&#34; 。
但严格来说,您的实施已经不遵守合同。 Iterator#next()
method的文档说:
抛出:
NoSuchElementException - 如果迭代没有更多元素
对你来说情况并非如此。您的实现只会在此处返回null
。当然,通过调用poll()
代替remove()
来调用NoSuchElementException
可以很容易地减轻这种情况,这会方便地抛出next()
,但我想这会与你当前的目标相矛盾。
我认为,至关重要的是,hasNext()
方法的实施会产生副作用,对外界可见。注释中已经给出了一个示例:当您创建其中两个迭代器实例时,两者都可能根据其合同行为,但两者的行为可能与预期的不同。
后者仅指单线程用法。当两个线程独立使用这些迭代器时,对next()
和batchWrite
的调用交织可能会导致竞争条件。 (当两个线程使用单个迭代器时更是如此,但所有迭代器就是这种情况,因为无论如何它们通常都是有状态的)。
底线是:虽然预期用法的一些细节仍然不清楚(特别是关于在<input type="text" pattern="[0-9]{9}">
方法中如何使用迭代器的问题,以及多个线程应该如何在这里进行交互的问题),这种实现它的方式很可能迟早会破坏,并且很难检测和重现这些错误。我建议在这里考虑替代实施。