之前一直以为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();
}