在Java 8中,排空队列的惯用方法是什么?

5

假设我有一个队列,我想要清空它。我需要做的是类似于以下的处理:

void emptyQueue(Queue<T> q) {
  T i;
  while ((i = q.poll()) != null)
    consume(i);
}

但这种方法感觉很古老。 我想要更像forEach方法的东西。当然,它是存在的——Queue是一个Collection——但它是遍历元素而不是消费它们。 理想情况下,我希望在Queue上有一个pollEach方法——但我似乎找不到合适的东西。 你如何编写这种代码?

你可以将消费者添加到 forEach 中... q.forEach(this::consume); 应该等同于你的代码。 - daniu
3
@daniu 不能在元素被消耗时从队列中删除这些元素。 - Didier L
2
你可以将 while 改为:for(T ti= null; (i = queue.poll()) != null; ){...} 这样可能会更好一些,因为 i 变量仅在 for 作用域内可用。 - Lino
1
如果您的队列继承自AbstractQueue,您可以简单地使用clear()方法。 - RealSkeptic
1个回答

6
您可以使用自己的生成器来调用队列上的poll()函数:
Stream.generate( () -> q.poll() )
    .takeWhile(Objects::nonNull) //Note that this is only available in java 9
    .forEach(i -> consume(i));

这种方法也是控制流传递的一个例子。你可以管理像阻塞等事情。在这种情况下,takeWhile 步骤只是展示了如何检测数据的结尾。


3
我非常喜欢这个解决方案,你可以把() -> q.poll()缩短为q::poll,也可以把i -> consume(i)缩短为this::consume(假设consume是类的实例成员)。 - Lino
1
请注意,Stream.generate 创建的是无序流,因此从语义上讲,即使它按顺序处理元素,在顺序执行中这也不是一个正确的解决方案(或者至少不等同于原始代码)。而且与“古老的”循环相比,它也没有任何优势。 - Holger

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