`PriorityQueue` 中的 `add` 和 `addAll` 表现不同,这是为什么?

`add` and `addAll` from a `PriorityQueue` behave differently, why is this?

将元素从 PriorityQueue 转移到 ArrayList 时,我注意到 List.addList.addAll 的行为不同。但我不确定为什么。

示例代码:

  public static void main(String[] args) {
    PriorityQueue<String> heap = new PriorityQueue<>(Comparator.reverseOrder());
    heap.add("a");
    heap.add("aa");
    heap.add("aaa");

    ArrayList<String> listAddAll = new ArrayList<>();
    listAddAll.addAll(heap);
    System.out.println(listAddAll);

    ArrayList<String> listAdd = new ArrayList<>();
    while (!heap.isEmpty()){
      listAdd.add(heap.remove());
    }
    System.out.println(listAdd);
  }

listAddAll 包含 [aaa, a, aa]listAdd 包含 [aaa, aa, a]。我希望两者都是后者,因为这是比较器指定的顺序。

因为 ArrayList.addAll 被实现为使用 Collection.toArray 像这样:

public boolean addAll(Collection<? extends E> c) {
    Object[] a = c.toArray();
    int numNew = a.length;
    ensureCapacityInternal(size + numNew);  // Increments modCount
    System.arraycopy(a, 0, elementData, size, numNew);
    size += numNew;
    return numNew != 0;
}

PriorityQueue.toArray只是底层数组的复制操作:

public Object[] toArray() {
        return Arrays.copyOf(queue, size);
}

因此,addAll 将根据它们在 queue 字段中的顺序插入队列元素,该字段是平衡二叉堆,将元素的顺序保留为树而不是列表。您得到的是表示树的原始数组,而不是排序列表。