Java 如何在不使用流阻塞的情况下处理队列的所有元素?

Java 如何在不使用流阻塞的情况下处理队列的所有元素?,java,queue,java-stream,Java,Queue,Java Stream,假设我有一个队列,我想清空队列的当前内容,并对每个元素执行一些操作。使用循环,我可以执行以下操作: while (true) { String element = queue.poll(); if (element == null) { return; } System.out.println(element); } 这感觉有点难看。我可以用streams做得更好吗 请注意,可能有其他线程同时访问队列,因此依赖队列的大小来了解要轮询的项目数很容易

假设我有一个
队列
,我想清空队列的当前内容,并对每个元素执行一些操作。使用循环,我可以执行以下操作:

while (true) {
    String element = queue.poll();
    if (element == null) {
        return;
    }
    System.out.println(element);
}
这感觉有点难看。我可以用streams做得更好吗


请注意,可能有其他线程同时访问队列,因此依赖队列的大小来了解要轮询的项目数很容易出错。

您不需要使用流来降低代码的难看程度(流解决方案可能会更难看)


您不需要使用流来使代码不那么难看(流解决方案可能会更难看)


目前我能想到的最好答案是:

StreamEx.generate(() -> queue.poll())
        .takeWhile(Objects::nonNull)
        .forEach(System.out::println);

但是它使用了一个库()。我们能用香草Java做到这一点吗?

目前我能想到的最好答案是:

StreamEx.generate(() -> queue.poll())
        .takeWhile(Objects::nonNull)
        .forEach(System.out::println);

但是它使用了一个库()。我们可以用vanilla Java实现这一点吗?

根据我的理解,如果您想使用stream,那么您不能修改正在进行操作的同一个集合

下面的代码可能会帮助您:

queue.stream().forEach(e -> {
        System.out.println(e);
    });
queue.clear();

根据我的理解,如果您想使用流,那么您不能修改正在进行操作的同一个集合

下面的代码可能会帮助您:

queue.stream().forEach(e -> {
        System.out.println(e);
    });
queue.clear();
由于您询问的是“无阻塞”,似乎您指的是
BlockingQueue
。在这种情况下,建议避免重复调用
poll()

而是一次性将所有挂起的元素转移到本地集合,然后处理它们:

List<String> tmp = new ArrayList<>();
queue.drainTo(tmp);
tmp.forEach(System.out::println);

List tmp=newarraylist();
drainTo队列(tmp);
System.out.println(String.join(System.lineSeparator(),tmp));
(虽然这不支持流操作).

既然您询问了“无阻塞”,似乎您指的是
阻塞队列。在这种情况下,建议避免重复调用
poll()

而是一次性将所有挂起的元素转移到本地集合,然后处理它们:

List<String> tmp = new ArrayList<>();
queue.drainTo(tmp);
tmp.forEach(System.out::println);

List tmp=newarraylist();
drainTo队列(tmp);
System.out.println(String.join(System.lineSeparator(),tmp));

(虽然这不需要流式操作).

我认为您不希望出现这种复杂情况,但如果我错了,您可以:

    Spliterator<String> spliterator = new Spliterators.AbstractSpliterator<String>(queue.size(), 0) {
        @Override
        public boolean tryAdvance(Consumer<? super String> action) {
            String element = queue.poll();
            if (element == null) {
                return false;
            } else {
                action.accept(element);
                return true;
            }
        }
    };
    StreamSupport.stream(spliterator, false).forEach(System.out::println);
Spliterator Spliterator=新的Spliterator.AbstractSpliterator(queue.size(),0){
@凌驾

public boolean tryAdvance(消费者我认为您不希望出现这种复杂情况,但如果我错了,您可以:

    Spliterator<String> spliterator = new Spliterators.AbstractSpliterator<String>(queue.size(), 0) {
        @Override
        public boolean tryAdvance(Consumer<? super String> action) {
            String element = queue.poll();
            if (element == null) {
                return false;
            } else {
                action.accept(element);
                return true;
            }
        }
    };
    StreamSupport.stream(spliterator, false).forEach(System.out::println);
Spliterator Spliterator=新的Spliterator.AbstractSpliterator(queue.size(),0){
@凌驾


public boolean tryAdvance(消费者不喜欢在测试中赋值。还有其他方法吗?
String s=queue.poll();而(s!=null){System.out.println(s);s=queue.poll();}
——本质上是@Kayaman在没有“丑陋”的情况下编写的打破了原来的问题。但是Kayaman写的内容是完全可以接受的。在我看来,在C语言中分配
while
条件是一个常见的习惯用法。我也不喜欢在Java中分配。不过,品味和习惯是个问题。遵循你的团队所做的。我真的不喜欢在测试中分配。还有其他方法吗?
String s=queue.poll();while(s!=null){System.out.println(s);s=queue.poll();}
——本质上是@Kayaman写的没有“丑陋”的东西打破了原来的问题。但是Kayaman写的东西是完全可以接受的。在我看来,在C语言中分配
while
条件是一个常见的习惯用法。我也不喜欢它在Java中。不过,品味和习惯的问题。跟随你的团队所做的。这到底比使用最简单的可用工具好多少?Streams没有这样做预先编写for和while循环之类的东西。在流没有增加任何价值的情况下使用流,您不会得到任何额外的分数。@Graemmoss是vanilla java中唯一不可用的东西(目前-它将在jdk-9中提供)是
takeWhile
;可以在您的项目中放入静态方法。这到底比使用最简单的可用工具好多少?Streams不反对像for和while循环这样的东西。在没有任何附加值的情况下使用Streams,您不会得到任何加分。@GraemeMoss是vani中唯一不可用的东西lla java(目前-将在jdk-9中提供)是
takeWhile
;可以放入项目内的静态方法中。当
queue.poll
报告为空时会发生什么情况,但之后还有其他线程,可能会将更多元素放入其中?此时您的流将被消耗…这一点很好,但我不介意在这种情况下,另一个线程是否将元素放入队列中我调用poll()后的ue据我所知,takeWhile
是您最好的选择。我在回答中也写了这一点,但不仅是
StreamX
已经生成,而且
Stream
也会返回nullThan。而且
takeWhile
可以作为静态方法添加到您的代码库中,直到java-9出现……当
queue.poll
rep时会发生什么orts null,但之后还有其他线程,这可能会将更多元素放入其中?此时您的流将被消耗…这一点很好,但我不介意在我调用poll()之后另一个线程将元素放入队列中据我所知,takeWhile
是您最好的选择。我在回答中也写了这一点,但不仅仅是
StreamX
已经生成,而且
Stream
也会返回null。而且
takeWhile
可以作为静态方法添加到您的代码库中,直到java-9出现为止……这可能会删除之后添加的项r
forEach
。这可能会删除在
forEach
之后添加的项目。我使用的是
ConcurrentLinkedQueue
,它不是一个
阻塞队列
,但在我的脑海中并没有固定下来,所以我可以更改它。@Holger,但不是