PriorityQueue经常被当成"自动排序的队列"用——这篇真实插入10个乱序整数,对比toArray()、iterator()遍历和poll()弹出三种方式,真实验证PriorityQueue到底维护的是什么顺序。
上一篇:String代理对真实验证
PriorityQueue底层是一个基于数组实现的二叉堆,只保证"父节点 <= 子节点"这一条堆性质,不保证整体有序。
PriorityQueueHeapOrderDemo.java int[] vals = {50, 30, 70, 10, 40, 60, 80, 20, 90, 5}; for (int v : vals) pq.add(v); pq.toArray(); // 直接拿内部数组 for (int v : pq) ...; // iterator()遍历
插入顺序: [50, 30, 70, 10, 40, 60, 80, 20, 90, 5] toArray() 真实内部数组顺序: [5, 10, 60, 30, 20, 70, 80, 50, 90, 40] iterator() 真实遍历顺序: 5 10 60 30 20 70 80 50 90 40 toArray() 真实是否已排序: false
真实结果证明 toArray() 和 iterator() 拿到的真实是堆内部数组的原始存储顺序——只有下标0(堆顶,最小值5)是确定的,其余位置只保证"父节点小于等于它的两个子节点",同一层的兄弟节点之间真实没有大小关系约束。这也是为什么示例里的第二个元素是10而不是20——10是堆顶5的子节点之一,它只需要比5大即可,跟30、70这些"看起来应该排在后面"的值之间真实没有约束关系。
既然遍历不保证顺序,那"优先级"到底体现在哪?真实测试反复poll()的结果。
PriorityQueueHeapOrderDemo.java while (!pq2.isEmpty()) pollOrder.append(pq2.poll());
poll() 真实依次弹出顺序: 5 10 20 30 40 50 60 70 80 90 真实验证堆性质(父<=子)全部成立: true
同一份数据,左边是树形结构(方便看"父 <= 子"这条堆性质),右边是数组的真实存储顺序(方便对照 toArray() 看到的结果)——每一步都是真实反射读出的 PriorityQueue.queue。