将元素从PriorityQueue
转移到ArrayList
时,我注意到List.add
和List.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]
。我希望两者都是后者,因为那是比较器指定的顺序。
答案 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
字段中插入队列元素,该字段是平衡二进制堆,将元素的顺序保留为树而不是列表。您将得到代表树的原始数组,而不是排序列表。