问题1:
以下输出为 1,2,3
Queue<Integer> q1 = new PriorityQueue<Integer>();
q1.add(1);
q1.add(3);
q1.add(2);
System.out.print(pq.poll());
System.out.print(pq.poll());
System.out.print(pq.poll());
以下输出为 1,3,2
Queue<Integer> q2 = new LinkedList<Integer>();
q3.add(1);
q3.add(3);
q3.add(2);
System.out.print(q3.poll());
System.out.print(q3.poll());
System.out.print(q3.poll());
为什么?由于它们都在实现队列接口但具有不同的行为?我认为无论实现类是什么,如果它们实现相同的接口,它的行为都必须相同。
问题2:
假设我用以下内容定义一个类
class process {
int exeTime;
int arrTime;
process(int, arr, int exe) {
arrTime=arr;
exeTime = exe;
}
}
在下面的代码行中重写比较方法会产生什么影响,为什么?
PriorityQueue<process> pq2 = new PriorityQueue<process>(new Comparator<process>() {
@Override
public int compare(process p1, process p2) {
if (p1.exeTime == p2.exeTime)
return p1.arrTime - p2.arrTime;
return p1.exeTime - p2.exeTime;
}
});
完全没有。 阅读Queue
接口文档:
队列通常(但不一定)以 FIFO(先进先出)方式对元素进行排序。例外情况包括优先级队列,它根据提供的比较器或元素的自然顺序对元素进行排序,以及LIFO队列(或堆栈),它对元素LIFO(后进先出)进行排序。无论使用什么顺序,队列的头部都是通过调用 remove() 或 poll() 删除的元素。在 FIFO 队列中,所有新元素都插入到队列的尾部。其他类型的队列可能使用不同的放置规则。每个队列实现都必须指定其排序属性。
Queue
的实现可以使用它选择的任何顺序。
2)队列将首先按exeTime
排序,如果exeTime
有平局,则按arrTime
排序。
- 是的,这两个类具有不同的行为,但它与
Queue
接口并不矛盾。
Queue
中用于add
的Javadocs没有说明任何特定的顺序:
如果可以在不违反容量限制的情况下立即将指定的元素插入到此队列中,则在成功时返回 true,如果当前没有可用空间,则引发 IllegalStateException。
Queue
中用于poll
的 Javadocs 可能会声明它从队列的头部获取,但add
没有说明哪个元素应该在队列的头部。
检索并删除此队列的头部,如果此队列为空,则返回 null。
由于Queue
没有指定任何特定的顺序,因此每个实现类都可以自由地为自己定义它。
- 你
- 没有覆盖任何东西;你指定了一个
Comparator
类,用于根据该构造函数的Javadocs
对PriorityQueue
中的元素进行排序。
创建具有默认初始容量的 PriorityQueue,其元素根据指定的比较器进行排序。
我认为无论实现类是什么,如果它们实现相同的接口,它的行为都必须相同。
这是不正确的。实现所要做的就是满足接口的协定。对于Queue
接口,行为可以像堆栈(先进,后出),像传统队列(先进先出),或者基于其他系统的返回元素。
PriorityQueue
根据元素的优先级返回元素,由Comparator
给出。如果 compare(a, b)
返回负整数,则a
的优先级高于 b
。如果compare(a, b)
返回一个正整数,则相反。如果compare(a, b)
返回0
,则a
和b
具有同等的优先级。