一、PriorityQueue详解
特点:
- 不能为null
- 元素可以重复
- 可以有序打印(每次只打印堆顶)
常用方法:
- add() 添加元素——不能添加null元素,否则抛空指针异常
- offer() 添加元素 ——不能添加null元素,否则抛空指针异常
- peek() 获取队列顶部元素——仅仅获取,没有删除
- element()获取堆顶元素——队列为空抛异常NoSuchElementException()
- remove() 删除元素:删除堆顶元素——队列为空的时候抛出异常NoSuchElementException()
- poll() 删除元素:删除堆顶元素——队列为空的时候返回null
源码分析:
- 继承关系
继承了AbstractQueue,AbstractQueue继承了AbstractCollection,实现了Queue接口
public class PriorityQueue<E> extends AbstractQueue<E>
public abstract class AbstractQueue<E>
extends AbstractCollection<E>
implements Queue<E> {
- 底层数据结构
用数组存储数据
用树来组织数据 - 基本属性
private static final int DEFAULT_INITIAL_CAPACITY = 11;//默认构造容量为11
private transient Object[] queue; //存储对象的数组
private int size = 0;//存储元素的个数
private final Comparator<? super E> comparator; //比较器
private transient int modCount = 0; //版本号
-
默认值
默认数组大小为11
-
构造函数(6个)
//无参构造一个默认容量的数组
public PriorityQueue() {
this(DEFAULT_INITIAL_CAPACITY, null);
}
//构造指定容量的空数组
public PriorityQueue(int initialCapacity) {
this(initialCapacity, null);
}
//构造指定容量的空数组。传入比较器
public PriorityQueue(int initialCapacity,
Comparator<? super E> comparator) {
if (initialCapacity < 1)
throw new IllegalArgumentException();
this.queue = new Object[initialCapacity];
this.comparator = comparator;
}
//传入Collection接口下的集合
public PriorityQueue(Collection<? extends E> c) {
if (c instanceof SortedSet<?>) {
SortedSet<? extends E> ss = (SortedSet<? extends E>) c;
this.comparator = (Comparator<? super E>) ss.comparator();
initElementsFromCollection(ss);
}
else if (c instanceof PriorityQueue<?>) {
PriorityQueue<? extends E> pq = (PriorityQueue<? extends E>) c;
this.comparator = (Comparator<? super E>) pq.comparator();
initFromPriorityQueue(pq);
}
else {
this.comparator = null;
initFromCollection(c);
}
}
//传入一个PriorityQueue接口下的集合
public PriorityQueue(PriorityQueue<? extends E> c) {
this.comparator = (Comparator<? super E>) c.comparator();
initFromPriorityQueue(c);
}
public PriorityQueue(SortedSet<? extends E> c) {
this.comparator = (Comparator<? super E>) c.comparator();
initElementsFromCollection(c);
}
- 增长方式
容量<64时,2倍扩容
容量>64时,1.5倍扩容
private void grow(int minCapacity) {
int oldCapacity = queue.length;
int newCapacity = oldCapacity + ((oldCapacity < 64) ?
(oldCapacity + 2) :
(oldCapacity >> 1));
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
queue = Arrays.copyOf(queue, newCapacity);
}
private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0) // overflow
throw new OutOfMemoryError();
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
}
- CRUD方法研究
1.添加元素:
add() / offer()
public boolean add(E e) {
return offer(e); //调用offer()
}
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; //直接将当前添加的数据放在0号位置
else
siftUp(i, e); //队中有元素,调用siftUp()向上调整
return true;
}
private void siftUp(int k, E x) {
if (comparator != null)
siftUpUsingComparator(k, x);
else
siftUpComparable(k, x);
}
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;
}
private void siftUpUsingComparator(int k, E x) {
while (k > 0) {
int parent = (k - 1) >>> 1; //无符号右移一位
Object e = queue[parent];
if (comparator.compare(x, (E) e) >= 0)
break;
queue[k] = e;
k = parent;
}
queue[k] = x;
}
2.删除元素:
remove()/ poll()
public E remove() {
E x = poll(); //调用poll进行删除
if (x != null) //当前队列不为空,则返回删除的元素
return x;
else //当前队列为空,返回异常NoSuchElementException()
throw new NoSuchElementException();
}
public E poll() {
if (size == 0) //队列中无元素,返回null
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 siftDown(int k, E x) {
if (comparator != null)
siftDownUsingComparator(k, x);
else
siftDownComparable(k, x);
}
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;
}
private void siftDownUsingComparator(int k, E x) {
int half = size >>> 1;
while (k < half) {
int child = (k << 1) + 1;
Object c = queue[child];
int right = child + 1;
if (right < size &&
comparator.compare((E) c, (E) queue[right]) > 0)
c = queue[child = right];
if (comparator.compare(x, (E) c) <= 0)
break;
queue[k] = c;
k = child;
}
queue[k] = x;
}
3.获取堆顶元素:
peek() / element()
public E peek() {
if (size == 0) //队列中没有元素,返回null
return null;
return (E) queue[0]; //队列不空,返回当前堆顶元素
}
public E element() {
E x = peek(); //调用peek()进行获取
if (x != null)
return x;
else
throw new NoSuchElementException();
}