Queue接口中的peek()方法

时间:2015-04-10 05:53:53

标签: java scjp

来自Java documentation

  

remove()和poll()方法删除并返回队列的头部。

     

element()和peek()方法返回,但不删除队列的头部。

从第二点开始,它说方法peek()返回队列的head元素,那么在下面的程序中它是如何返回队列的head元素的呢?

public class PQ {

public static void main(String[] args) {
    PriorityQueue<String> pq = new PriorityQueue<String>();
    pq.add("carrot"); 
    pq.add("apple"); 
    pq.add("banana");
    System.out.println(pq.poll() + ":" + pq.peek()); // prints apple and banana rather than apple and apple
}
}

一旦删除了第一个元素(胡萝卜),apple就会成为队列的头部(根据队列中的FIFO),所以peek()方法应该返回苹果吗?

例2:

public class PQ {

public static void main(String[] args) {
    PriorityQueue<String> pq = new PriorityQueue<String>();
    pq.add("carrot"); 
    pq.add("apple"); 
    pq.add("banana");
    System.out.println(pq); // prints [apple, carrot, banana] -> it should be [apple, banana, carrot] right? if it is following natural sorting order
}
}

5 个答案:

答案 0 :(得分:8)

因为你是第一次投票

System.out.println(pq.poll() + ":" + pq.peek());

由于它是优先级队列元素存储为

carrot -> banana -> apple

当您poll()获得apple并从队列中删除时。在此之后,队列头部为banana,这正是您peek()时获得的。

  

请在更新的问题中查看示例2。排序很奇怪

这正是你所期待的。您可以看到documentation

  

方法iterator()中提供的迭代器不保证以任何特定顺序遍历优先级队列的元素。如果需要有序遍历,请考虑使用Arrays.sort(pq.toArray())。

如果您读取java优先级队列使用的优先级堆数据结构,您将更好地理解这一点。您应该使用poll(), peek()方法来获取有序数据。

答案 1 :(得分:2)

您正在使用PriorityQueue而不是java.util.Queue(常规队列) PriorityQueue根据Comparable :: compareTo()方法的实现对元素进行排序,该方法是String.class的自然排序(字母顺序)。

因此,队列中的元素将是apple-banana-carrot。 输出符合预期

答案 2 :(得分:2)

您已通过引用文档自行回答了问题。

您的优先级队列包含

apple, banana, carrot

poll返回“apple”然后删除它。所以队列现在是

banana, carrot

peek然后返回“banana”

答案 3 :(得分:2)

POLL()方法将从队列中删除该元素并将元素返回到调用方法。 PEEK()方法只返回该元素。 参考POLL()和PEEK()方法的实现代码:

public E poll() {
        if (this.size == 0)
            return null;
        int i = --this.size;
        this.modCount += 1;
        Object localObject1 = this.queue[0];
        Object localObject2 = this.queue[i];
        this.queue[i] = null; 
        if (i != 0)
            siftDown(0, localObject2);
        return localObject1;
}

public E peek() {
        return ((this.size == 0) ? null : this.queue[0]);
}

答案 4 :(得分:2)

Queue接口定义了一些处理列表第一个元素的方法,这些方法的行为方式不同。这些方法是:

peek()
element()
poll()
remove()

peek()此方法检索队列的第一个元素的值,而不将其从队列中删除。对于方法的每次调用,我们总是得到相同的值,并且它的执行不会影响队列的大小。如果队列为空,则peek()方法返回null。

元素()此方法的行为类似于peek(),因此它再次检索第一个元素的值而不删除它。但是,如果列表为空,则element()会抛出NoSuchElementException。

poll()此方法通过从队列中删除队列的第一个元素来检索该值。 。在每次调用时,它都会删除列表的第一个元素,如果列表已经为空,则返回null,但不会抛出任何异常。

remove()此方法的行为与poll()方法相同,因此它会删除列表的第一个元素,如果列表为空,则会抛出NoSuchElementException