添加不可比较的对象时,PriorityQueue 的大小会增加
Size of PriorityQueue increases when non-comparable objects are added
考虑以下代码:
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
在此代码中,首先将不可比较的对象添加到 PriorityQueue
。此代码工作正常,。
然后,第二个对象被添加到这个队列中。根据 PriorityQueue.add
Javadoc 的预期,抛出 ClassCastException
因为第二个对象与第一个对象不可比。
然而,尽管抛出异常,但似乎队列的大小增加了:第二个打印语句输出 2 而不是 1。
这种行为是预期的吗?如果是这样,这背后的原因是什么?记录在哪里?
offer
的源代码(由 add
调用)揭示了将非 Comparable
对象传递给 PriorityQueue
时出现的无效状态没有 Comparator
.
public boolean More 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;
}
在调用 siftUp
之前修改了大小。 siftUp
方法,通常负责将元素插入队列,(最终)抛出 ClassCastException
,但大小已被修改,导致大小不正确。
似乎没有记录表明 size
即使出现 ClassCastException
也会递增。一个简单的修复方法是将行 size = i + 1;
放在 if/else 之后和 return 语句之前。
根据 GrepCode.com 的 version of the source,看起来这可能是他们实现中的一个错误。
add 函数所做的就是调用
public boolean add(E e) {
return offer(e);
}
报价函数如下所示
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;
}
您会注意到在通过 siftUp 实际插入项目之前调用了 size = i + 1。调用 siftUp 时,它做的第一件事是尝试转换为 Comparable 并在实际插入项目之前抛出异常。因此它会增加大小而不实际插入项目。
考虑以下代码:
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
在此代码中,首先将不可比较的对象添加到 PriorityQueue
。此代码工作正常,
然后,第二个对象被添加到这个队列中。根据 PriorityQueue.add
Javadoc 的预期,抛出 ClassCastException
因为第二个对象与第一个对象不可比。
然而,尽管抛出异常,但似乎队列的大小增加了:第二个打印语句输出 2 而不是 1。
这种行为是预期的吗?如果是这样,这背后的原因是什么?记录在哪里?
offer
的源代码(由 add
调用)揭示了将非 Comparable
对象传递给 PriorityQueue
时出现的无效状态没有 Comparator
.
public boolean More 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;
}
在调用 siftUp
之前修改了大小。 siftUp
方法,通常负责将元素插入队列,(最终)抛出 ClassCastException
,但大小已被修改,导致大小不正确。
似乎没有记录表明 size
即使出现 ClassCastException
也会递增。一个简单的修复方法是将行 size = i + 1;
放在 if/else 之后和 return 语句之前。
根据 GrepCode.com 的 version of the source,看起来这可能是他们实现中的一个错误。
add 函数所做的就是调用
public boolean add(E e) {
return offer(e);
}
报价函数如下所示
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;
}
您会注意到在通过 siftUp 实际插入项目之前调用了 size = i + 1。调用 siftUp 时,它做的第一件事是尝试转换为 Comparable 并在实际插入项目之前抛出异常。因此它会增加大小而不实际插入项目。