PriorityQueue(优先级队列)源码分析及常用方法解析
2019-03-08 13:37
507 查看
一、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(); }
相关文章推荐
- Java源码解析阻塞队列ArrayBlockingQueue常用方法
- android PriorityQueue优先级队列解析
- Google Test(GTest)使用方法和源码解析——参数自动填充技术分析和应用
- Google Test(GTest)使用方法和源码解析——结果统计机制分析
- 【Java】HashMap源码分析——常用方法详解
- Google Test(GTest)使用方法和源码解析——私有属性代码测试技术分析
- dhtmlx5源码解析(一)全局方法分析 dhtmlxValidation&&浏览器类型
- jquery源码解析:jQuery队列操作queue方法实现的原理
- String类常用方法源码分析
- 分布式消息队列RocketMQ源码分析之1 -- Topic路由数据结构解析 -- topicRoute与topicPublishInfo与queueId
- dhtmlx5源码解析(二)全局方法分析date&&ajax
- RecyclerView 的常用方法;工作原理与ListView比较;源码解析
- Google Test(GTest)使用方法和源码解析——模板类测试技术分析和应用
- java学习之旅57、58--数组_StringBuilder和StringBuffer的使用_JDK源码分析内部机制、常用方法补充_常见面试题答法
- 解析Java中PriorityQueue优先级队列结构的源码及用法
- 有关LinkedList常用方法的源码解析
- 基于ArrayList常用方法的源码全面解析
- 有关ArrayList常用方法的源码解析
- java学习之旅56--数组_StringBuilder和StringBuffer的使用_常用方法_方法链的实现_JDK源码分析
- 给jdk写注释系列之jdk1.6容器(12):PriorityQueue源码解析PriorityQueue是一种什么样的容器呢?看过前面的几个jdk容器分析的话,看到Queue这个单词你一定会,哦~这