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

时间:2017-05-16 14:02:43

标签: java queue java-stream

假设我有Queue<String>并且我想清空队列的当前内容并对每个元素执行某些操作。使用循环我可以做类似的事情:

while (true) {
    String element = queue.poll();
    if (element == null) {
        return;
    }
    System.out.println(element);
}

这感觉有点难看。我能用溪流做得更好吗?

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

5 个答案:

答案 0 :(得分:2)

由于您询问了“ without blocking ”,因此您似乎指的是BlockingQueue。在这种情况下,建议避免重复调用poll()

相反,将所有待处理元素一次性转移到本地集合,然后处理它们:

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

您还可以避免多次System.out(隐式)同步:

List<String> tmp=new ArrayList<>();
queue.drainTo(tmp);
System.out.println(tmp.stream().collect(Collectors.joining(System.lineSeparator())));

List<String> tmp=new ArrayList<>();
queue.drainTo(tmp);
System.out.println(String.join(System.lineSeparator(), tmp));

(虽然这不支持流操作)...

答案 1 :(得分:1)

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

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

string stdalph = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456‌​789"; 
string ourkey = "xMK6JDC18hLoYeEkBSlIyVO0niadRf9qH5N4tbWpZ3wgAuc7GQjXm2FUvTz‌​Prs"; 
StringBuilder sbalph = new StringBuilder(stdalph); 
StringBuilder sbkey = new StringBuilder(ourkey); 
textBox2.Text = textBox1.Text;

答案 2 :(得分:0)

您不需要使用流来减少代码的丑陋(流解决方案可能会更难看)。

String s = null;
while((s = queue.poll()) != null)
    System.out.println(s);

答案 3 :(得分:0)

目前我能想出的最佳答案如下:

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

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

答案 4 :(得分:0)

我认为你不想要并发症,但如果我错了,你可以这样做:

    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);

您可以查看SpliteratorsStreamSupport的文档,了解各种可能的改进。