如何自定义 PriorityQueue.stream().foreach 以按优先顺序迭代

How to customize PriorityQueue.stream().foreach to iterate in priority order

我有一个 class,其中包含 PriorityQueue 字段:

public class MyClass<T>{
    Queue<T> queue = new PriorityQueue<>();

我想以某种方式从 MyClass 获取流并使用 foreach 并希望序列按照我的 PriorityQueue 的优先顺序运行。最简单的方法是覆盖 stream() 方法:

@Override
public Stream stream() {
    return queue.stream();
}

但这不会按优先顺序公开队列元素。所以问题是:如何使 foreach 流方法的行为类似于:

    while(!queue.isEmpty()) 
        queue.poll();

您可以使用 Stream::generate and Queue::poll 方法创建一个 Stream,其中包含来自 PriorityQueue 的元素并保持它们的顺序:

@Override
public Stream<T> stream() {
    return Stream.generate(queue::poll);
}

但是这可能很危险,因为 Stream::generate 将不断调用 poll,因此它可能是一个无限流。因此,应考虑使用 Stream::limit 和队列大小:

@Override
public Stream<T> stream() {
    return Stream.generate(queue::poll)
        .limit(queue.size());
}

或者您可以简单地 return 排序流 :

@Override
public Stream<T> stream() {
    return queue.stream()
            .sorted(comparator);
}

comparator 是你的比较器。

Java 9 中,您可以将 Stream::takeWhile 与拒绝空值的谓词一起使用。由于 Queue::poll 将 return null 当队列为空时 - 结果 Stream 将按顺序包含队列中的元素(这是使用 limit 的替代方法在第一个解决方案中描述):

@Override
public Stream<T> stream() {
    return Stream.generate(queue::poll)
            .takeWhile(Objects::nonNull);
}