Consider the following code:
import java.util.PriorityQueue;
public class Test {
public static void main(String argv[]) {
PriorityQueue<A> queue = new PriorityQueue<>();
System.out.println("Size of queue is " + queue.size()); // prints 0
queue.add(new A()); // does not throw an exception
try {
queue.add(new A()); // this time, an exception is thrown
} catch (ClassCastException ignored) {
System.out.println("An exception was thrown");
}
System.out.println("Size of queue is " + queue.size()); // prints 2
}
}
class A { } // non-comparable object
In this code, a non-comparable object is first added to a PriorityQueue
. This code works fine, as already answered here.
Then, a second object is added to this queue. As expected per PriorityQueue.add
Javadoc, a ClassCastException
is thrown because the second object is not comparable to the first one.
However, it seems that the size of the queue was increased although an exception was thrown: the second print statement outputs 2 instead of 1.
Is this behaviour expected? If so, what is the reason behind this and where is it documented?
According to GrepCode.com's version of the source, it looks like it may be a bug in their implementation.
All the add function does is call
public boolean add(E e) {
return offer(e);
}
The offer function looks like this
public boolean offer(E e) {
if (e == null)
throw new NullPointerException();
modCount++;
int i = size;
if (i >= queue.length)
grow(i + 1);
size = i + 1;
if (i == 0)
queue[0] = e;
else
siftUp(i, e);
return true;
}
You'll notice that size = i + 1 is called before the item is actually inserted via siftUp. When siftUp is called, the very first thing that it does is try to cast to Comparable and throws the exception before actually inserting the item. Therefore it increments the size without actually inserting an item.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With