4

我做了以下测试,看看如何

PriorityBlockingQueue<String> pq = new PriorityBlockingQueue<>(2);
     pq.put("Sing");
     pq.put("Sing2");
     pq.put("Sing3");
     pq.put("Sing4");
     pq.put("Sing10");
     pq.put("Sing11");
     pq.put("Sing12");
     pq.put("Sing13");
     for (String s1: pq)
     {
         System.out.print(s1 +" ");
     }

我得到的结果是:

 Sing Sing10 Sing11 Sing13 Sing2 Sing3 Sing12 Sing4

现在,如果在构建时没有指定比较器, API应该如何按自然顺序对它们进行排序。但是,您可以看到结果根本没有排序。

其次,我设置的初始容量是2,如果实际上没有设置边界,为什么会有这样的选项?重点是什么?我知道 api 指定它是一个无界的优先级队列,但是如果构造函数不能设置任何边界,为什么还要让构造函数获取初始容量呢?

所以基本上我有两个问题:

1)为什么上面发布的结果的顺序不遵循元素的自然顺序?

2)拥有一个带有参数“初始容量”的构造函数的目的是什么,实际上并没有设置界限。在LinkedBlockingQueue中这是合理的,因为它设置了边界,但它不会发生在 PriorityBlockingQueue 中。

提前致谢。

4

4 回答 4

10

例如,当您使用 poll、remove、peek 或 take 访问头部时,可以保证顺序,但在迭代时则不能:

方法 iterator() 中提供的 Iterator 不能保证以任何特定顺序遍历优先级队列的元素。

这将产生预期的输出:

String s;
while ((s = pq.poll()) != null) {
    System.out.println(s);
}

输出:

Sing
Sing10
Sing11
Sing12
Sing13
Sing2
Sing3
Sing4

具有参数“初始容量”的构造函数的目的是什么,该参数实际上并未设置界限。

初始容量不受限制。队列由数组支持 - 通过设置初始容量,您可以避免不必要的数组大小调整(类似于 ArrayList 的构造函数)。

于 2013-07-18T14:41:27.670 回答
5

javadoc 说:

方法 iterator() 中提供的 Iterator 不能保证以任何特定顺序遍历 PriorityBlockingQueue 的元素。如果您需要有序遍历,请考虑使用 Arrays.sort(pq.toArray())。

使用时,您将按顺序获取元素peek()/poll()/take()。但不是在迭代时。

要回答您的第二个问题:队列在内部实现为对象数组。设置初始容量可以避免在队列增长并且元素数量超过容量时出现过多的数组副本。就像一个 ArrayList。

于 2013-07-18T14:40:17.003 回答
1

初始容量是使用@-) 初始化存储元素的容器的大小。随着元素的添加,容量会自动增长。这取决于增长策略(由底层容器定义)扩展容器大小的成本是多少。

PriorityBlockingQueue根据其定义,它是一个无界阻塞队列。拥有这样一个带有参数“初始容量”的构造函数的目的是用一个对实际用例有意义的值来初始化底层容器。这是 的实现者无法预见的PriorityBlockingQueue

LinkedBlockingQueue根据其定义,它是一个可选的有界阻塞队列。因此,如果设置了参数,则该参数具有充当上限的功能。

于 2013-07-18T14:48:28.133 回答
0

检查此链接

方法 iterator() 中提供的 Iterator 不能保证以任何特定顺序遍历 PriorityBlockingQueue 的元素。如果您需要有序遍历,请考虑使用 Arrays.sort(pq.toArray())。此外,方法 drainTo 可用于按优先级顺序删除部分或所有元素并将它们放置在另一个集合中。

于 2013-07-18T14:46:16.393 回答