文章目录

  • 前言
  • 一、Queue接口
    • Queue接口的特点:
    • QueueAPI的方法:
  • 二、PriorityQueue
    • 构造器
    • 扩容机制:
    • 方法:
      • add()和offer()
      • remove(Object o)和poll()
      • element()和peek()
  • 三 、top K问题:
  • 总结

前言


提示:以下是本篇文章正文内容,下面案例可供参考

一、Queue接口

数据可重复,保证有序性(基于数据类型)、不可以存储null。

Queue接口的特点:

队列的主要特点是在基本的集合方法之外,还提供特殊的插入、获取和检验操作。每个操作都提供两个方法,一种返回异常,一种返回null或者false.
队列一般满足先进先出规则(FIFO),除了优先队列(priority queue)和栈(stack),但是栈是FILO(先进后出规则),优先队列自己定义了排序规则。

QueueAPI的方法:

  • add(E e) 插入一个元素到队列中,失败时返回IllegalStateException (队列容量不够)
  • element() 返回队列头部的元素
  • offer(E e) 插入一个元素到队列中,失败时返回false
  • peek() 返回队列头部的元素,队列为空时返回null
  • poll() 返回并移除队列的头部元素,队列为空时返回null
  • remove() 返回并移除队列的头部元素

二、PriorityQueue

构造器

两个参数的作用:
int initialCapacity, //初始容量
Comparator<? super E> comparator //自定义比较器

public PriorityQueue() {//private static final int DEFAULT_INITIAL_CAPACITY = 11;//默认初始容量:this(DEFAULT_INITIAL_CAPACITY, null);}public PriorityQueue(int initialCapacity) {this(initialCapacity, null);}public PriorityQueue(Comparator<? super E> comparator) {this(DEFAULT_INITIAL_CAPACITY, comparator);}public PriorityQueue(int initialCapacity,Comparator<? super E> comparator) {if (initialCapacity < 1)//参数合法性检验throw new IllegalArgumentException();//自定义初始容量//底层默认this.queue = new Object[initialCapacity];this.comparator = comparator;}

扩容机制:

原来队列长度小于64 2倍+2扩容大于64 1.5倍扩容

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//最大扩容量比较//如果新扩容大于最大扩容量边界 用原数组长度和扩容边界比较,如果大于最大扩容量边界返回int最大值,如果小于返回最大扩容边界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;}

方法:

add()和offer()

从源码上看PriorityQueue的入列操作没有对所有加入的元素进行优先级排序。而是只保证数组父节点数据小于子节点数据。

public boolean add(E e) {return offer(e);}
public boolean offer(E e) {if (e == null)//PriorityQueue不能存储nullthrow new NullPointerException();modCount++;int i = size;if (i >= queue.length) //数组扩容grow(i + 1);//扩容参数为i+1siftUp(i, e);size = i + 1;return true;}private void siftUp(int k, E x) {if (comparator != null) //判断是否使用类部比较器类型siftUpUsingComparator(k, x, queue, comparator);elsesiftUpComparable(k, x, queue);}//PriorityQueue默认的比较器实现了小根堆private static <T> void siftUpComparable(int k, T x, Object[] es) {Comparable<? super T> key = (Comparable<? super T>) x;while (k > 0) {int parent = (k - 1) >>> 1; //找出父节点Object e = es[parent];if (key.compareTo((T) e) >= 0)//传入值和父节点比较如果大于父节点将数据存入到当前的位置,否则父节点数据下移继续向上查询break;es[k] = e;k = parent;}es[k] = key;//key赋值}

remove(Object o)和poll()

原理:取出头部数据,将末尾数据从头部向下检验知道找到合适他的位置

 public E poll() {final Object[] es;final E result;if ((result = (E) ((es = queue)[0])) != null) { //根节点有数据modCount++;final int n;final E x = (E) es[(n = --size)];//最后一共数据es[n] = null;//末尾设置为null方便垃圾回收if (n > 0) {final Comparator<? super E> cmp;//判断是否为使用默认比较强if ((cmp = comparator) == null)siftDownComparable(0, x, es, n);elsesiftDownUsingComparator(0, x, es, n, cmp);}}return result;}public boolean remove(Object o) {int i = indexOf(o); //查找此数据是否存在存在返回该数据所在位置,不存在返回-1if (i == -1)return false;//数据不存在返回falseelse {removeAt(i);return true;}}E removeAt(int i) {// assert i >= 0 && i < size;final Object[] es = queue;modCount++;int s = --size;//size-1if (s == i) // 此数据正好是末尾数据es[i] = null;//数据覆盖,方便垃圾回收else {E moved = (E) es[s];//取出末尾数据es[s] = null;//末尾设置为null方便垃圾回收siftDown(i, moved);if (es[i] == moved) {siftUp(i, moved);if (es[i] != moved)return moved;}}return null;}

element()和peek()

public E element() {//如果存在返回该值不存在抛出异常E x = peek();if (x != null)return x;elsethrow new NoSuchElementException();}public E peek() {//如果存在返回该值不存在返回nullreturn (E) queue[0];}

三 、top K问题:

查找指定数据中出现次数最多的前K个数据:
比如:求前K个最大数据,我们创建一个容量为K的底层为小根堆的队列每次插入数据只需要与根数据比较决定是否插入即可,相反求最小数据就创建一个大跟堆。

 public static void BufferedReaderEx(String str) {//指定文件目录File file = new File(str); //file实例FileReader reader = null;//读取数据并存储在list集合中try {reader = new FileReader(file);BufferedReader bufferedReader = new BufferedReader(reader);String tmp;ArrayList<String> list = new ArrayList<>();while ((tmp = bufferedReader.readLine()) != null) {String[] split = tmp.split(",");for (String s:split){list.add(s);}}HashMap<String,Integer> map = HashMapEx(list);PriorityQueue<Map.Entry<String, Integer>> queue = QueueEx(map,5);while (!queue.isEmpty()){Map.Entry<String, Integer> remove = queue.remove();System.out.println("数字:" + remove.getKey() + ",出现:" +remove.getValue() + "次");}}  catch (IOException e) {e.printStackTrace();}}public static HashMap<String,Integer> HashMapEx(ArrayList<String> list){//将数据存储到HashMap中用来统计一个数组出现的次数 key为数据 value为出现次数HashMap<String, Integer> map = new HashMap<>();while (!list.isEmpty()){String index = list.remove(0);if (map.containsKey(index)) {map.put(index, map.get(index) + 1);} else {map.put(index, 1);}}return map;}public static PriorityQueue<Map.Entry<String, Integer>> QueueEx(HashMap<String,Integer> map,int num){//将Map中的Entry存储到PriorityQueue队列中并提供一个关于Entry.value的比较器并将队列的容量设置为KPriorityQueue<Map.Entry<String, Integer>> queue = new PriorityQueue<>(num, new Comparator<Map.Entry<String, Integer>>() {@Overridepublic int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2) {return (Integer) o1.getValue() - (Integer) o2.getValue();}});Iterator<Map.Entry<String, Integer>> iterator = map.entrySet().iterator();while (iterator.hasNext()){//遍历Map集合 如果队列容量小于K直接插入数据否则与queue顶部数据进行Value计较如果大于顶部数据插入到queue中Map.Entry<String, Integer> next = iterator.next();if(queue.size()<num){queue.add(next);}else {if(next.getValue()>queue.peek().getValue()){queue.remove();queue.add(next);}}}return queue;}

总结

Queue接口保证数据有序性(基于数据类型)、不可以存储nullPriorityQueue介绍可以自定义比较器用来实现自己想要的底层结构方便我们最值问题和topK问题的求解。

Queue接口及是实现类PriorityQueue介绍相关推荐

  1. JAVA并发类包介绍

    JAVA并发Apl介绍合集 1. java.util.concurrent包 1.1 Executors线程池 1.2 Queues队列 1.3 Concurrent Collections 1.4 ...

  2. Java™ 教程(Queue接口)

    Queue接口 Queue是在处理之前保存元素的集合,除了基本的Collection操作外,队列还提供额外的插入.删除和检查操作,Queue接口如下. public interface Queue&l ...

  3. java反射获取实现类_Java介绍通过反射获取类的信息

    免费学习推荐:java基础教程 目录1.获取Field 2.反编译Field 3.通过反射机制访问对象属性 4.可变长度参数 5.反射Method(了解) 6.反编译(了解) 7.反射机制调用方法 8 ...

  4. 12 带音视频、多媒体、2D3D显示加速的嵌入式类芯片介绍

    带音视频.多媒体.2D3D显示加速的嵌入式类芯片介绍 作者 将狼才鲸 创建日期 2022-04-11 带硬件音视频编解码模块的芯片有两类: 一是不包含GPU(支持OpenGL ES.Open VG等协 ...

  5. JESD204接口调试总结——JESD204C协议的介绍

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 JESD204接口调试总结--JESD204C协议的介绍 前言 JESD204C变化总结 新术语 传输层 数据链路层 物理层 第二部分 ...

  6. android 继承类图,Android Studio中绘制UML类图介绍

    Android Studio中绘制UML类图介绍 Android Studio中绘制UML类图介绍 动机 最近开始阅读项目源码,从其中一个模块开始看,奈何大项目中的一个模块,对于萌新而言,也太过于复杂 ...

  7. Android - 接口回调 interface(类外部接口)

    链接是类内部的接口:https://blog.csdn.net/u012246458/article/details/91446288 下面是类外部的接口→ 介绍: 使用接口的核心原因:为了能够向上转 ...

  8. Java的基础语法(8)-- API常见的类的介绍匿名对象

    十五.API 15.1.概述: API(Application Programming Interface),应用程序编程接口.Java API是一本程序员的字典,是JDK中提供给我们使用的类的说明文 ...

  9. Collection接口和Map接口的主要实现类

    Collection接口和Map接口的主要实现类 Collection接口 Collection是最基本的集合接口,一个Collection代表一组Object,即Collection的元素(Elem ...

最新文章

  1. zerodivisionerror什么意思python-python代码里出现是啥意思
  2. 史上最全的并发编程学习
  3. 使用代码生成具有层级结构的IBASE
  4. django+xadmin在线教育平台(十二)
  5. mongodb删除文档
  6. 再生龙u盘复制linux,再生龙制作U盘启动盘教程 | 楚盟博客
  7. ajax=1,ajax专栏1
  8. 11.9 noip模拟试题
  9. Atitit 健康减肥与软件健康减肥的总结 attilax著 1. 几大最佳实践减肥行为 1 1.1. 控制饮食分量用小碗 小盘子 小餐具 1 1.2. 软件如何减肥,控制资源占有率,比如体积 打包
  10. 广数928te_广数928TE系统说明书
  11. 【uart篇】synopsys uart vip配置使用
  12. 错误报告函数:strerror和perror
  13. Windows系统,文件和文件夹命名规则
  14. 阿里云服务器操作系统怎么选择?
  15. PAT --- 1068.万绿丛中一点红 (20 分)
  16. mysql 性能优化,减轻数据库的压力。(减少数据库查询的次数)
  17. Vibrant Ink Theme for IntelliJ IDEA
  18. 追赶法求解块三对角矩阵以及matlab代码实现
  19. BQ40Z80 CHG DSG打不开
  20. java 解压zip文件

热门文章

  1. 【Laravel-海贼王系列】第七章,Pipeline 类解析
  2. 探寻新的治疗方法,研究人员用VR可视化DNA结构
  3. python 类属性及限制
  4. 【算法】快速排序算法的编码和优化
  5. jquery easyui datagrid实现单行的上移下移,以及保存移动的结果
  6. Centos7下安装Docker1.8
  7. Linux下安装jdk1.6和tomcat
  8. 邮箱的创建及配置:Exchange2003系列之二
  9. .Net/C# 实现: FlashFXP 地址簿中站点密码的加解密算法
  10. TortoiseSVN图标设置在注册表中的位置