“ PriorityQueue”中的“ add”和“ addAll”的行为不同,这是为什么呢?

时间:2020-05-26 07:12:56

标签: java collections priority-queue

将元素从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]。我希望两者都是后者,因为那是比较器指定的顺序。

1 个答案:

答案 0 :(得分:2)

因为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字段中插入队列元素,该字段是平衡二进制堆,将元素的顺序保留为树而不是列表。您将得到代表树的原始数组,而不是排序列表。

相关问题