偷看()或不偷看()
Posted
技术标签:
【中文标题】偷看()或不偷看()【英文标题】:To peek() or not to peek() 【发布时间】:2016-03-21 12:13:25 【问题描述】:我有 PriorityQueue 使用示例,它产生
3
1
1
1
5
0
这是代码
import java.util.*;
class Someclass
public static class IntegerWr
implements Comparable<IntegerWr>
Integer val;
IntegerWr(Integer val)
this.val = val;
public void change(Integer nval)
this.val = nval;
@Override
public int compareTo(IntegerWr iw)
return val.compareTo(iw.val);
@Override public String toString()
return ""+val;
public static void main (String[] args)
PriorityQueue<IntegerWr> pq = new PriorityQueue<>();
pq.add(new IntegerWr(3));
System.out.println(pq.peek());
IntegerWr iw1 = new IntegerWr(1);
pq.add(iw1);
System.out.println(pq.peek());
pq.add(new IntegerWr(4));
System.out.println(pq.peek());
pq.add(new IntegerWr(2));
System.out.println(pq.peek()); //must output 1, and does so
iw1.change(5); //change value of element that is actually on peek
System.out.println(pq.peek()); //outputs 5 which is unexpected
pq.add(new IntegerWr(0));
System.out.println(pq.peek());
似乎 PriorityQueue 仅在插入时订购。使用什么方法来获取实际的 peek()?
【问题讨论】:
"似乎 PriorityQueue 仅在插入时订购。"——确实如此。队列怎么知道你修改了某个元素?例如,如果您将项目添加到列表中,然后对其进行排序,然后更改其某些值以破坏顺序,您难道不希望列表以某种方式考虑它吗?.. 【参考方案1】:您正在更改存储在队列中的对象内部的值。 队列对对象的内容一无所知。 因此,当您在队列中的对象上调用方法时(如在 'iw1.change(5)' 中),队列中的任何内容都不知道。 您需要存储一个替换对象,以便队列对元素重新排序。
【讨论】:
可以poll()
该项目,修改它,然后offer()
它回到队列以保持正确的顺序。【参考方案2】:
代替iw1.change(5);
做:
pq.remove(iw1);
iw1.change(5);
pq.add(iw1);
【讨论】:
对象的变化发生在某个时间。优先级队列构建一次,寿命更长。 change() 可能会在以后的任何时间发生。如果对象被更改,PriorityQueue peek() 不会给出正确的(通过存储对象的自然排序)结果。 :// @willmore 同样适用于 java 中具有某种排序的所有类型的集合,一旦将对象添加到此类对象,就无法更改构成排序条件的对象的属性收藏。 (这甚至适用于某些集合,例如没有特定顺序的 Maps)【参考方案3】:PriorityQueue 是队列的一个实现。如果我们查看Queue interface,它有 peek()、poll()、remove() 方法。
peek()
方法返回但不移除队列的头部。
poll()
方法移除并返回队列的头部。从队列中删除的确切元素是队列的排序策略的函数。
import java.util.*;
class Someclass
public static class IntegerWr
implements Comparable<IntegerWr>
Integer val;
IntegerWr(Integer val)
this.val = val;
public void change(Integer nval)
this.val = nval;
@Override
public int compareTo(IntegerWr iw)
return val.compareTo(iw.val);
@Override public String toString()
return ""+val;
public static void main (String[] args)
PriorityQueue<IntegerWr> pq = new PriorityQueue<>();
pq.add(new IntegerWr(3));
System.out.println(pq.peek());
IntegerWr iw1 = new IntegerWr(1);
pq.add(iw1);
System.out.println(pq.peek());
pq.add(new IntegerWr(4));
System.out.println(pq.peek());
pq.add(new IntegerWr(2));
System.out.println(pq.peek()); //must output 1, and does so
iw1.change(5); //change value of element that is actually on peek
System.out.println(pq.peek()); //outputs 5 which is unexpected
pq.add(new IntegerWr(0));
System.out.println(pq.peek());
System.out.println("Elements ordered");
Object o = null;
while ((o = pq.poll()) != null) //poll() method removes and return
//the head of the queue.
//Exactly which element is removed
//from the queue is a function
//of the queue's ordering policy
System.out.println(o);
输出
3
1
1
1
5
0
Elements ordered
0
2
3
4
5
要按顺序获取 PriorityQueue 的元素,请使用poll()
。
【讨论】:
以上是关于偷看()或不偷看()的主要内容,如果未能解决你的问题,请参考以下文章