关于push()、pop()、offer()、poll()

本文解析了Java集合框架中Deque接口的实现原理,重点比较了push和offer方法的区别,以及它们与pop、poll、peek、element等操作的关系,展示了ArrayDeque类的具体实现和Queue与Deque的不同之处。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

之前一直以为push和offer方法都一样,今天做一道题,使用栈进行实现。发现有所不同,读一下源码观察一下

发现源码都是封装好的hh—源码读起来真开心

// Deque 继承自 Queue 继承自 Collection 继承自 Iterable--Iterable实现迭代器
public interface Deque<E> extends Queue<E> {}

public interface Queue<E> extends Collection<E> {}

public interface Collection<E> extends Iterable<E> {}

Queue

Queue实际上是实现了一个先进先出(FIFO:First In First Out)的有序表。定义了以下方法:

  • int size():获取队列长度;
  • boolean add(E)/boolean offer(E):添加元素到队尾;
  • E remove()/E poll():获取队首元素并从队列中删除;
  • E element()/E peek():获取队首元素但并不从队列中删除。

注意到添加、删除和获取队列元素总是有两个方法,这是因为在添加或获取元素失败时,这两个方法的行为是不同的。
在这里插入图片描述
AbstractQueue抽象类中:

	public boolean add(E e) {
        if (offer(e))
            return true;
        else
            throw new IllegalStateException("Queue full");
    }

    public E remove() {
        E x = poll();
        if (x != null)
            return x;
        else
            throw new NoSuchElementException();
    }

    public E element() {
        E x = peek();
        if (x != null)
            return x;
        else
            throw new NoSuchElementException();
    }

可以看到,add方法添加元素到队尾,添加失败时会抛出异常;offer方法使用时会返回一个布尔值。
offer、poll、peek方法都是在实现add、remove、element中使用到的。
源码就很清晰。

Deque

允许两头都进,两头都出,这种队列叫双端队列(Double Ended Queue),学名Deque。

Java集合提供了接口Deque来实现一个双端队列,它的功能是:

  • 既可以添加到队尾,也可以添加到队首;
  • 既可以从队首获取,又可以从队尾获取。

在这里插入图片描述

public class ArrayDeque<E> extends AbstractCollection<E> implements Deque<E>, Cloneable, Serializable{}
// *** Basic methods ***

	// 添加元素到队首,如果满了,调用方法扩容到double
    public void addFirst(E e) {
        if (e == null)
            throw new NullPointerException();
        elements[head = (head - 1) & (elements.length - 1)] = e;
        if (head == tail)
            doubleCapacity();
    }

    public void addLast(E e) {
        if (e == null)
            throw new NullPointerException();
        elements[tail] = e;
        if ( (tail = (tail + 1) & (elements.length - 1)) == head)
            doubleCapacity();
    }
	
	// offer在这里是调用了add方法,但是会返回一个布尔值
    public boolean offerFirst(E e) {
        addFirst(e);
        return true;
    }

    public boolean offerLast(E e) {
        addLast(e);
        return true;
    }

	// remove方法这里是调用poll方法,如果poll出来的是空则抛出异常
    public E removeFirst() {
        E x = pollFirst();
        if (x == null)
            throw new NoSuchElementException();
        return x;
    }

    public E removeLast() {
        E x = pollLast();
        if (x == null)
            throw new NoSuchElementException();
        return x;
    }

	// poll方法这里是从头或者尾部取出值,如果是null就返回null,否则返回结果,同时将head或者tail指针移动一位
    public E pollFirst() {
        int h = head;
        @SuppressWarnings("unchecked")
        E result = (E) elements[h];
        // Element is null if deque empty
        if (result == null)
            return null;
        elements[h] = null;     // Must null out slot
        head = (h + 1) & (elements.length - 1);
        return result;
    }

    public E pollLast() {
        int t = (tail - 1) & (elements.length - 1);
        @SuppressWarnings("unchecked")
        E result = (E) elements[t];
        if (result == null)
            return null;
        elements[t] = null;
        tail = t;
        return result;
    }
	
	// get方法通过elements方法得到结果,如果get不到会抛出异常
    public E getFirst() {
        @SuppressWarnings("unchecked")
        E result = (E) elements[head];
        if (result == null)
            throw new NoSuchElementException();
        return result;
    }

    public E getLast() {
        @SuppressWarnings("unchecked")
        E result = (E) elements[(tail - 1) & (elements.length - 1)];
        if (result == null)
            throw new NoSuchElementException();
        return result;
    }

	// peek方法是取出队首或者队尾的元素,但不删除---调用elements方法
    @SuppressWarnings("unchecked")
    public E peekFirst() {
        // elements[head] is null if deque empty
        return (E) elements[head];
    }

    @SuppressWarnings("unchecked")
    public E peekLast() {
        return (E) elements[(tail - 1) & (elements.length - 1)];
    }


// *** Queue methods ***---单独对队列方法增加了几个api
// 因为队列是先进先出,因此添加元素都是在队尾,然后取出或者操作元素都是在队首
// add和offer是添加到队尾,remove和poll是删除队首元素,element和peek是取出队首元素
// add--remove、 offer--poll

	// add是加到队尾,addLast是void类型并返回布尔值
	public boolean add(E e) {
        addLast(e);
        return true;
    }

	// offerLast方法是boolean类型
    public boolean offer(E e) {
        return offerLast(e);
    }

    public E remove() {
        return removeFirst();
    }

    public E poll() {
        return pollFirst();
    }

    public E element() {
        return getFirst();
    }

    public E peek() {
        return peekFirst();
    }

// *** Stack methods *** 
// 栈是先进后出,因此添加元素是添加到队首,取出元素也是在队首---对应push--pop

    public void push(E e) {
        addFirst(e);
    }

    public E pop() {
        return removeFirst();
    }

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值