Queue 源码阅读
仅大致过了下,有问题的请指出,谢谢。
版本
1.8
介绍
主要接口及实现
队列接口,抽象实现,优先级队列
双端队列接口,双端队列实现
- Queue
- abstract class AbstractQueue<E>
- class PriorityQueue<E> extends AbstractQueue<E>
- Deque
- class LinkedList<E> implements Deque<E>
- class ArrayDeque<E> implements Deque<E>
public interface Queue<E> extends Collection<E> public abstract class AbstractQueue<E> extends AbstractCollection<E> implements Queue<E> class PriorityQueue<E> extends AbstractQueue<E> public interface Deque<E> extends Queue<E> class LinkedList<E> extends AbstractSequentialList<E> implements List<E>, Deque<E> class ArrayDeque<E> extends AbstractCollection<E> implements Deque<E>
(一)LinkedList
基于链表实现的双端队列。
介绍略。主要是实现了Deque的进offer
、出poll
、取peek
系列函数。
(二)ArrayDeque
基于数组实现的双端队列。
属性
transient
为了自定义序列化,减少存储损耗。- head和tail保存头尾索引。
- 最小容量为8.
transient Object[] elements
transient int head
transient int tail
private static final int MIN_INITIAL_CAPACITY = 8
构造器
- 默认容量:16
- 指定容量:需大于
MIN_INITIAL_CAPACITY =8
,且保证容量为2的指数倍,保证方法calculateSize
head
和tail
取默认值,0(成员变量赋对应类型默认零值)
public ArrayDeque() {
elements = new Object[16];
}
public ArrayDeque(int numElements) {
allocateElements(numElements);
}
// 测试:传入9,返回16;传入17,返回32
private static int calculateSize(int numElements) {
int initialCapacity = MIN_INITIAL_CAPACITY;
if (numElements >= initialCapacity) {
initialCapacity = numElements;
initialCapacity |= (initialCapacity >>> 1);
initialCapacity |= (initialCapacity >>> 2);
initialCapacity |= (initialCapacity >>> 4);
initialCapacity |= (initialCapacity >>> 8);
initialCapacity |= (initialCapacity >>> 16);
initialCapacity++;
if (initialCapacity < 0) // Too many elements, must back off
initialCapacity >>>= 1;// Good luck allocating 2 ^ 30 elements
}
return initialCapacity;
}
进
默认:尾部进
public void addLast(E e) {
if (e == null)
throw new NullPointerException();
elements[tail] = e;
if ( (tail = (tail + 1) & (elements.length - 1)) == head)
doubleCapacity();
}
扩容
扩容方法为:doubleCapacity()
前提:容量满
大致流程:
1. 保存索引:head、tail、当前容量…
2. 计算新容量:elements.length << 1
3. 防止超出类型值int
范围
4. 分配内存
5. 赋值并移动:由于数组队列为循环结构,需使用两次System.arrcopy
;另外,head置0,tail置原长度
private void doubleCapacity() {
assert head == tail;
int p = head;
int n = elements.length;
int r = n - p; // number of elements to the right of p
int newCapacity = n << 1;
if (newCapacity < 0)
throw new IllegalStateException("Sorry, deque too big");
Object[] a = new Object[newCapacity];
System.arraycopy(elements, p, a, 0, r);
System.arraycopy(elements, 0, a, r, p);
elements = a;
head = 0;
tail = n;
}
出
默认:首部出
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 int size() {
return (tail - head) & (elements.length - 1);
}
空判断
public boolean isEmpty() {
return head == tail;
}
(三)PriorityQueue
基于数组实现的优先级队列。
属性
- 默认容量:11
- 默认比较器:null
private static final int DEFAULT_INITIAL_CAPACITY = 11;
transient Object[] queue
private int size = 0
private final Comparator<? super E> comparator
transient int modCount = 0
扩容
容量小于64,容量增加一倍;容量大于等于64,容量增加50%。
private void grow(int minCapacity) {
int oldCapacity = queue.length;
// Double size if small; else grow by 50%
int newCapacity = oldCapacity + ((oldCapacity < 64) ?
(oldCapacity + 2) :
(oldCapacity >> 1));
// overflow-conscious code
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
queue = Arrays.copyOf(queue, newCapacity);
}
进
默认尾部进,向上调整
public boolean offer(E e) {
if (e == null)
throw new NullPointerException();
modCount++;
int i = size;
if (i >= queue.length)
grow(i + 1);
size = i + 1;
if (i == 0)
queue[0] = e;
else
siftUp(i, e);
return true;
}
向上调整
private void siftUpComparable(int k, E x) {
Comparable<? super E> key = (Comparable<? super E>) x;
while (k > 0) {
int parent = (k - 1) >>> 1;
Object e = queue[parent];
if (key.compareTo((E) e) >= 0)
break;
queue[k] = e;
k = parent;
}
queue[k] = key;
}
出
默认首部出,取尾部元素复制给queue[0]
,向下调整
public E poll() {
if (size == 0)
return null;
int s = --size;
modCount++;
E result = (E) queue[0];
E x = (E) queue[s];
queue[s] = null;
if (s != 0)
siftDown(0, x);
return result;
}
向下调整
private void siftDownComparable(int k, E x) {
Comparable<? super E> key = (Comparable<? super E>)x;
int half = size >>> 1; // loop while a non-leaf
while (k < half) {
int child = (k << 1) + 1; // assume left child is least
Object c = queue[child];
int right = child + 1;
if (right < size &&
((Comparable<? super E>) c).compareTo((E) queue[right]) > 0)
c = queue[child = right];
if (key.compareTo((E) c) <= 0)
break;
queue[k] = c;
k = child;
}
queue[k] = key;
}
内置迭代器
迭代器遍历数组,即堆按照自顶向下,自左向右的方式遍历。