When transferring elements from a PriorityQueue
to an ArrayList
I noticed List.add
and List.addAll
behave differently. But I'm not sure why.
Example code:
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);
}
The listAddAll
contains [aaa, a, aa]
while listAdd
contains [aaa, aa, a]
. I'd expect both to be the latter as that is the order specified by the comparator.
Because the ArrayList.addAll
is implemented to use Collection.toArray
like this:
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;
}
And PriorityQueue.toArray
is just a copy operation of the underlying array:
public Object[] toArray() {
return Arrays.copyOf(queue, size);
}
So, addAll
will insert the queue elements according to their order in the queue
field which is balanced binary heap that preserves the order of elements as a tree not a list. You're getting the raw array representing the tree not a sorted list.