Java 8中的PriorityBlockingQueue流无序

时间:2015-08-04 00:42:50

标签: java java-8 java-stream priority-queue

这两段代码具有不同的输出顺序。 第一篇:

while(!jobQueue.isEmpty()) {
    TimeoutJobRequest job = jobQueue.peek();
    if(job.isReady()) {
        execute(job);
        jobQueue.poll();
    } else {
        return;
    }
}

第二部分:

jobQueue.stream()
        .filter(TimeoutJobRequest::isReady)
        .peek(jobQueue::remove)
        .forEach(this::execute);

请注意,jobQueuePriorityBlockingQueue

重新排序仅在this::execute相对较长时(例如几秒钟)发生。

4 个答案:

答案 0 :(得分:7)

stream的{​​{1}}遵循PriorityBlockingQueue顺序,根据documentation

  

不保证方法iterator()中提供的迭代器   遍历任何特定的PriorityBlockingQueue的元素   顺序。

如果您想要优先顺序,则需要Iterator poll中的元素。

PriorityBlockingQueue

输出(可能取决于Java实现):

PriorityBlockingQueue<Integer> pq = new PriorityBlockingQueue<>();
pq.add(5);
pq.add(8);
pq.add(3);

System.out.println("-- Try 1 --");
pq.stream().forEach(System.out::println);

System.out.println("-- Try 2 --");
IntStream.range(0, pq.size()).map(i -> pq.poll()).forEach(System.out::println);

答案 1 :(得分:4)

如果要创建遵循队列顺序的流,可以尝试以下代码(它清空队列):

Stream.generate(jobQueue::poll).limit(jobQueue.size())

答案 2 :(得分:1)

第一段代码不等于第二段代码,当job.isReady()函数返回false时,第一段代码终止,但第二段仍然运行,函数filter为stream只是一个过滤操作

您可以将第一段代码更改为

while(!jobQueue.isEmpty()) {
    TimeoutJobRequest job = jobQueue.peek();
    if(job.isReady()) {
        execute(job);
        jobQueue.poll();
    } 
}

答案 3 :(得分:0)

不幸的是,迭代顺序!=优先顺序。

我准备了两个可复制粘贴的解决方案,使用Stream API使用优先级顺序遍历PriorityQueue

static <T> Stream<T> drainToStream(PriorityQueue<T> queue) {
    Objects.requireNonNull(queue);
    return Stream.generate(queue::poll)
      .limit(queue.size());
}

static <T> Stream<T> asStream(PriorityQueue<T> queue) {
    Objects.requireNonNull(queue);
    Comparator<? super T> comparator = queue.comparator();
    return comparator != null
      ? queue.stream().sorted(comparator)
      : queue.stream().sorted();
}

draintToStream清空队列,而asStream保持原始队列不变。