PriorityQueue简介
优先级队列继承AbstractQueue,实现了java.ioSerializable。
1,成员变量
// 默认容量
private static final int DEFAULT_INITIAL_CAPACITY = 11;
/**
* 数组存储,数组存储的是堆内元素
*/
private transient Object[] queue;
/**
* 优先队列内元素个数
*/
private int size = 0;
/**
* 比较器
*/
private final Comparator<? super E> comparator;
/**
*修改次数
*/
private transient int modCount = 0;
2,我们来看看它的构造函数
/**
* 创建一个具有默认初始容量(11),根据其自然顺序对其元素PriorityQueue。
*/
public PriorityQueue() {
this(DEFAULT_INITIAL_CAPACITY, null);
}
/**
* 创建与根据其自然顺序对其元素指定的初始容量创建一个PriorityQueue。
*/
public PriorityQueue(int initialCapacity) {
this(initialCapacity, null);
}
/**
* 创建与根据指定的比较器对其元素指定的初始容量创建一个PriorityQueue。
*/
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;
}
/**
* 创建一个包含指定优先级队列中的元素一个PriorityQueue
*/
@SuppressWarnings("unchecked")
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);
}
}
/**
* 创建一个包含指定有序set的元素一个PriorityQueue.
*/
@SuppressWarnings("unchecked")
public PriorityQueue(PriorityQueue<? extends E> c) {
this.comparator = (Comparator<? super E>) c.comparator();
initFromPriorityQueue(c);
}
@SuppressWarnings("unchecked")
public PriorityQueue(SortedSet<? extends E> c) {
this.comparator = (Comparator<? super E>) c.comparator();
initElementsFromCollection(c);
}
它是基于小根堆(父节点小于子节点)这个数据结构实现的。这里牵涉到了大小关系,元素大小的评判可以通过元素本身的自然顺序,也可以通过构造时传入的比较器
现在我们给它添加一个元素
add():添加一个元素
添加一个元素,就会破坏原有小根堆的形式,所以我们要进行调整。siftUp()方法就是对它进行调整
我们也可以通过构造函数来用优先级队列构造一个大根堆。比较的时候我们可以传入我们想要的对象
2,remove():删除一个元素
删除一个元素后要对它重新进行调整。
接下来看一个运用优先级队列的小例子
找100000个数字中重复最少的十个数
public class Test10 {
public static void main(String[] args) {
/**
* 初始化100000个数字
*/
Random random = new Random();
ArrayList<Integer> number = new ArrayList<Integer>(100000);
for(int i = 0; i < 100000;i++){
number.add(random.nextInt(100000));
}
minTen(number);
}
/**
* 100000个数字 里重复最少的十个数
* 使用小根堆
* @param number
*/
private static void minTen(ArrayList<Integer> number) {
// TODO Auto-generated method stub
/**
* 将数和重复次数分别当作键和值存入hashmap中
*/
HashMap<Integer, Integer> hashmap = new HashMap<Integer, Integer>();
for(int i = 0;i < number.size();i++){
if(!hashmap.containsKey(number.get(i))){
hashmap.put(number.get(i), 0);
}else{
hashmap.put(number.get(i), hashmap.get(number.get(i))+1);
}
}
/**
* 重写Comparator里的compare()方法 将优先级队列比较的东西变为比较value值
*/
PriorityQueue<Map.Entry<Integer, Integer>> priorityQueue = new PriorityQueue<Map.Entry<Integer, Integer>>(new Comparator<Map.Entry<Integer, Integer>>(){
@Override
public int compare(Entry<Integer, Integer> o1, Entry<Integer, Integer> o2) {
// TODO Auto-generated method stub
return o2.getValue()-o1.getValue();
}
});
/**
* 遍历hashmap 构造大根堆 o2.getValue()-o1.getValue() 完成需要的是个最小的数
*/
Iterator<Map.Entry<Integer, Integer>> iterator = hashmap.entrySet().iterator();
while(iterator.hasNext()){
Map.Entry<Integer, Integer> next = iterator.next();
if(priorityQueue.size() == 10){
if(next.getValue() < priorityQueue.peek().getValue()){
priorityQueue.remove();
priorityQueue.add(next);
}
}else{
priorityQueue.add(next);
}
}
while(priorityQueue.size() > 0){
System.out.printf(priorityQueue.remove().getKey()+" ");
}
}
}