PriorityQueue主要原始碼解析
阿新 • • 發佈:2018-12-17
簡介:PriorityQueue優先佇列,是Queue的實現類,但不具有先進先出的特點,而是根據自然排序或者自定義排序進行內部排序的,自然排序下(如儲存Integer,String)會根據從小到大排序,自定義排序可以根據自己定義的比較方法排序。
1.Priority的底層是陣列,初始化長度為11,下面是PriorityQueue的主要建立方法
private static final int DEFAULT_INITIAL_CAPACITY = 11; private transient Object[] queue; //呼叫無參構造時初始化一個長度為11的陣列 public PriorityQueue() { this(DEFAULT_INITIAL_CAPACITY, null); } //直接指定陣列長度 public PriorityQueue(int initialCapacity) { this(initialCapacity, null); } //指定陣列長度和比較器 public PriorityQueue(int initialCapacity, Comparator<? super E> comparator) { // Note: This restriction of at least one is not actually needed, // but continues for 1.5 compatibility if (initialCapacity < 1) throw new IllegalArgumentException(); this.queue = new Object[initialCapacity]; this.comparator = comparator; }
2.新增元素:add(E e)和offer(E e),兩個方法其實是一樣的,add方法內部就是呼叫offer方法
新增一個元素時,先判斷當前元素加入是否越界,即用引數size(表示當前數組裡的元素個數)判斷是否大於佇列長度,若大於則呼叫grow()方法擴充套件佇列,然後將size+1,若元素為空,將元素放在首位,否則呼叫siftUp()方法將元素存入陣列
public boolean add(E e) { return offer(e); } 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 grow(int minCapacity) { int oldCapacity = queue.length; // 當原陣列長度小於64,每次將長度+2,否則擴充套件成原來的1.5倍 int newCapacity = oldCapacity + ((oldCapacity < 64) ? (oldCapacity + 2) : (oldCapacity >> 1)); // 若新陣列長度大於MAX_ARRAY_SIZE,則呼叫hugeCapacity比較minCapacity是否大於MAX_ARRAY_SIZE,若大於就把新陣列長度賦為Integer.MAX_VALUE,否則為MAX_ARRAY_SIZE 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; }
siftUp()將元素存入陣列
// 判斷是否有自定義比較器,沒有則有自然排序
private void siftUp(int k, E x) {
if (comparator != null)
siftUpUsingComparator(k, x);
else
siftUpComparable(k, x);
}
//自然排序:k即陣列最後元素的下標,從後往前遍歷,有元素比x大的,即往後移一位,知道有元素比x小,對出迴圈,將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;
}
3.刪除元素
poll():刪除並返回佇列頭的元素,如果沒有元素可取,返回null
remove():刪除並返回佇列頭的元素,如果沒有元素可取,報異常
remove(Object o):遍歷陣列查詢元素的下標,刪除下標
peek():返回佇列頭的元素,不刪除
//將第一個元素刪除,然後將後面的元素往前移,將最後的元素賦為null
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;
}
public E remove() {
E x = poll();
if (x != null)
return x;
else
throw new NoSuchElementException();
}
public boolean remove(Object o) {
int i = indexOf(o);
if (i == -1)
return false;
else {
removeAt(i);
return true;
}
}
public E peek() {
if (size == 0)
return null;
return (E) queue[0];
}
siftDown():將元素往前移
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;
}
4.例子
import java.util.Comparator;
import java.util.Iterator;
import java.util.PriorityQueue;
public class QueueTest {
public static void main(String[] args) {
//自然排序
PriorityQueue<Integer> queue=new PriorityQueue<>();//初始化長度為11
queue.offer(1);
queue.add(1);
queue.add(3);
queue.add(2);
int i=0;
while(i++<10){
// System.out.println(queue.peek());//輸出1,1,1,1,...,1,1
// System.out.println(queue.poll());//輸出1,2,3,null,null,null,...,用poll時,如果佇列為空,即返回null
// System.out.println(queue.remove());//輸出1,2,3,然後報異常
}
//自定義排序,引入自定義比較器,否則會報類轉換異常
PriorityQueue<Student> students=new PriorityQueue<>(10, new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
// TODO Auto-generated method stub
return o1.getAge()-o2.getAge();
}
});
students.add(new Student(10, "張三"));
students.add(new Student(8, "李四"));
students.add(new Student(12, "王五"));
for(Student student:students){
System.out.println(student);
}
Iterator<Student> iterator = students.iterator();
while(iterator.hasNext()){
Student next = iterator.next();
System.out.println(next.getAge()+"=="+next.getName());
}
}
}
Student類
package newCode;
public class Student {
private int age;
private String name;
public Student(int age,String name) {
// TODO Auto-generated constructor stub
this.age=age;
this.name=name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Student [age=" + age + ", name=" + name + "]";
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}