为什么我得到以下结果?

时间:2013-07-18 14:34:46

标签: java concurrency priority-queue

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

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)具有参数“initial capacity”的构造函数的目的是什么,该参数实际上没有设置边界。在LinkedBlockingQueue中它是合理的,因为它设置了绑定,但它不会发生在PriorityBlockingQueue中。

提前致谢。

4 个答案:

答案 0 :(得分:10)

当您使用poll,remove,peek或take例如,但是在迭代时访问头部时,保证顺序:

  

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

这将产生预期的输出:

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

输出:

Sing
Sing10
Sing11
Sing12
Sing13
Sing2
Sing3
Sing4

  

使用具有参数“initial capacity”的构造函数的目的是什么,该参数实际上没有设置边界。

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

答案 1 :(得分:5)

javadoc说:

  

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

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

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

答案 2 :(得分:1)

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

PriorityBlockingQueuedefinition的无界阻塞队列。具有参数“初始容量”的这种构造函数的目的是使用对实际用例有意义的值初始化基础容器。 PriorityBlockingQueue的实施者无法预见到这一点。

LinkedBlockingQueuedefinition的可选绑定阻塞队列。所以参数有 - 如果设置 - 该函数作为上限。

答案 3 :(得分:0)

选中此link

  

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