Collection的其它两大分支:List和Set在前面已近分析过,这篇来分析一下Queue的底层实现。

前三篇关于Java容器类的文章:

java容器类1:Collection,List,ArrayList,LinkedList深入解读

java容器类2:Map及HashMap深入解读

java容器类3:set/HastSet/MapSet深入解读

Queue


public interface Queue<E> extends Collection<E> {boolean add(E var1);boolean offer(E var1);E remove();E poll();E element();E peek();
}

这就是Queue接口的代码,相比于List或者Set简洁明了很多。下面介绍一下它里面接口的含义:
在处理元素前用于保存元素的 collection。除了基本的 Collection 操作外,队列还提供其他的

插入、提取和检查

操作。每个方法都存在两种形式:

一种抛出异常(操作失败时),另一种返回一个特殊值(null 或 false,具体取决于操作)。

插入操作的后一种形式是用于专门为有容量限制的 Queue 实现设计的;在大多数实现中,插入操作不会失败。
 

AbstractQueue


AbstractQueue中实现了queue和Collection中部分函数,比较简单,源码如下:

public abstract class AbstractQueue<E> extends AbstractCollection<E>implements Queue<E> {
    protected AbstractQueue() {}
    public boolean add(E e) {if (offer(e))return true;elsethrow new IllegalStateException("Queue full");}public E remove() {E x = poll();if (x != null)return x;elsethrow new NoSuchElementException();}public E element() {E x = peek();if (x != null)return x;elsethrow new NoSuchElementException();}public void clear() {while (poll() != null);}public boolean addAll(Collection<? extends E> c) {if (c == null)throw new NullPointerException();if (c == this)throw new IllegalArgumentException();boolean modified = false;for (E e : c)if (add(e))modified = true;return modified;}
}

从上面的调用关系可以看出来,Queue的解释中哪些是会抛出异常的调用,哪些是不会抛出异常的调用接口。

Deque


一个线性 collection,支持在两端插入和移除元素。名称 deque 是“double ended queue(双端队列)”的缩写,通常读为“deck”。大多数 Deque 实现对于它们能够包含的元素数没有固定限制,但此接口既支持有容量限制的双端队列,也支持没有固定大小限制的双端队列。(java 1.6版本中的家扣,1.8中接口有变动,但是大概含义相似)

在Java容器类1中介绍了LinkedList,链表类其实实现了 Deque的接口,所以链表支持从头部和尾部添加和移除元素。

ArrayDeque


因为链表的存储结构可能比较简单,这里介绍一下ArrayDeque,它的里面存储元素使用一个数组。 作为一个双端队列的数组,涉及到扩容和元素的拷贝的逻辑可能比较复杂些。

看一下里面的几个构造函数:

public ArrayDeque() {elements = 

new Object[16];

    }public ArrayDeque(int numElements) {

allocateElements(numElements);

    }public ArrayDeque(Collection<? extends E> c) {allocateElements(c.size());addAll(c);}

从构造函数可以看出默认的会分配一个长度为16的数组。同时,也支持指定大小的队列(这里的allocateElements函数之前在

java容器类2:Map及HashMap深入解读  中已经深入分析过,是个非常精妙的函数)。下面看一下到底是如何实现插入?又是如何自动扩充数组的?

ArrayQueue中维护了两个成员变量:head和tail分别代表 队列的头和尾在数组中的下标。

 /*** The index of the element at the head of the deque (which is the* element that would be removed by remove() or pop()); or an* arbitrary number equal to tail if the deque is empty.*/transient int head;/*** The index at which the next element would be added to the tail* of the deque (via addLast(E), add(E), or push(E)).*/transient int tail;

在队列的首部添加元素:

public void addFirst(E e) {if (e == null)throw new NullPointerException();

elements[head = (head - 1) & (elements.length - 1)] = e;

        if (head == tail)

doubleCapacity();

    }

public void

addLast(E e) {

if

 (e == 

null

)

throw new

 NullPointerException();elements[tail] = e;

if

 ( (tail = (tail + 1) & (elements.length - 1)) == head)doubleCapacity();
}

由构造函数和数组分配的函数可以知道,数组的长度肯定是一个2的幂次方的一个整数。

当head为大于0的整数时,在头部插入很简单,将head前一个元素赋值为e就可以了。那么当head为0时,怎么计算的?由上面可以看出会插入到数组的尾部。所以ArrayDeque相当于在一个圆环上,规定一个头一个尾作为队列的前后(将数组的首位相连)。

在最后位置添加元素的原理和在首部添加相似。注意判断是否已满的 判断,这里不再分析。

当队列已经满后,会将数组的长度double。由于数组是不能自由扩张的,所以doubleCapacity函数应该是分配一个更大的数组,并将原来的元素拷贝进去,这里不再分析。

总的来说双端队列ArrayDeque是在数组的基础之上实现,原理和实现都不算复杂,但是很多边界调节等细节可以斟酌。

BlockingQueue


BlockingQueue是concurrent包下面的,后续打算写一个系列文章专门分析concurrent包下面的类,及一些多线程相关的东西。

PriorityQueue


优先级队列是一个可以排序的队列。内部是一个最大堆,大部分人应该了解堆排序,所以对最大堆应该不会陌生。

每次读取元素都是读取最大的元素(默认情况下)。

对外的接口有如下:

方法名 功能描述
add(E e) 添加元素
clear() 清空
contains(Object o) 检查是否包含当前参数元素
offer(E e) 添加元素
peek() 读取元素,(不删除)
poll() 取出元素,(删除)
remove(Object o) 删除指定元素
size() 返回长度

PriorityQueue 默认是一个最大堆结构,如果想构造一个最小堆:

private static final int DEFAULT_INITIAL_CAPACITY = 11;
PriorityQueue<Integer> maxHeap=new PriorityQueue<Integer>(DEFAULT_INITIAL_CAPACITY, new Comparator<Integer>() {@Overridepublic int compare(Integer o1, Integer o2) {return o2-o1;}});

关于堆的数据结构部分这里不再分析可以参考:https://www.cnblogs.com/tstd/p/5125949.html

c++版的优先级队列分析:优先级队列用法详解(priority_queue)

由于是通过数组保存数据,所以优先级队列也会涉及到容量的扩充等,和HashMap/Setting/Collection的扩容原理相同,甚至更简单,不再分析。PriorityQueue内部的操作都是在最大堆的基础上展开的,阅读堆的数据结构相关资料便可了解。

参考:

http://tool.oschina.net/uploads/apidocs/jdk-zh/java/util/Deque.html

http://www.cnblogs.com/NeilZhang/p/5650226.html

ava容器类4:Queue深入解读相关推荐

  1. java容器类4:Queue深入解读

    Collection的其它两大分支:List和Set在前面已近分析过,这篇来分析一下Queue的底层实现. 前三篇关于Java容器类的文章: java容器类1:Collection,List,Arra ...

  2. C++ STL : 模拟实现STL中的容器适配器stack和queue

    目录 什么是容器适配器 stack stack的文档介绍-(来自cplusplus) stack的实现 queue queue的文档介绍-(来自cplusplus) queue的实现 什么是容器适配器 ...

  3. C++中的deque、stack、queue及priority_queue

    C++中的deque.stack.queue及priority_queue 文章目录 C++中的deque.stack.queue及priority_queue 一.deque 二.stack 三.q ...

  4. c++中的queue容器

    queue容器 队列是一种容器适配器,专门用于在FIFO上下文(先进先出)中操作,其中从容器一端插入元素,另一端 提取元素. 队列作为容器适配器实现,容器适配器即将特定容器类封装作为其底层容器类,qu ...

  5. C++ 容器适配器(stack、queue、priority_queue)

    容器适配器 首先,我们要明白适配器是干什么的?其实就是一个接口转换装置,是得我们能用特定的方法去操作一些我们本来无法操作的东西.举一个例子,比如你的一个设备支持串口线,而你的电脑支持的是usb口,这时 ...

  6. STL库:stack和queue

    STL库:stack和queue 文章目录 STL库:stack和queue 1.STL库中stack的官方介绍 2.stack的常用接口 3.stack的模拟实现 4.STL库中queue的官方介绍 ...

  7. 【C++】手把手教你写出自己的Stack和Queue类

    在上一篇文章中,我介绍了如何模拟实现 list容器,今天我们来实现 栈(Stack)和队列(Queue). 我将 栈 与队列放置在一起的原因是 这两种数据结构 是十分相似的,将他们放在一起可以相互比较 ...

  8. C++ queue的使用及模拟实现

    目录 queue的简单介绍 queue的使用 queue() push() pop() empty() size() front() back() swap() queue的模拟实现 成员变量 成员函 ...

  9. C++ STL : 模拟实现STL中的容器适配器priority_queue

    目录 priority_queue 文档介绍 实现思路 思路 仿函数 实现 priority_queue 文档介绍 文档介绍 优先队列是一种容器适配器,根据严格的弱排序标准,它的第一个元素总是它所包含 ...

最新文章

  1. JS:1.2,控制语句(if,if else,for,switch,while,do while)
  2. [VNC] 分辨率, 退出全屏,
  3. 2010-07-18 项目重构计划
  4. CodeBlocks的一些用法和常见的问题
  5. 机器学习(三十一)——Linear Discriminant Analysis
  6. mysql 查看锁表日志_MYSQL 表锁情况查看
  7. 160 - 5 ajj.2
  8. Linux中常用文件的含义
  9. 计算机绘制轴类零件图,轴类零件工序图自动绘制的方法和系统研究
  10. 三星CEO承认:可折叠智能手机Galaxy Fold开卖得太着急
  11. C/C++训练项目一:2048
  12. 6月29 Electron的第一课
  13. firebug下载时出现there was an error loading firebug
  14. 快递查询单号查询追踪,一键查询全部物流
  15. Android Camera硬件结构组成(一)之 手机摄像头的组成结构和工作原理
  16. float 范围 java_Java中float/double取值范围与精度
  17. 7-13 盲盒包装流水线
  18. Revit二次开发_获取视图样式替换
  19. Python实现整蛊恶搞程序生成exe文件小弹窗祝福发给好兄弟好闺蜜好室友
  20. 3d量测怎么学距离_3D虚拟仿真技术提升物流设备应用能力

热门文章

  1. python第三方库-基础
  2. Python web开发——自定义userprofile(用户描述)
  3. tomcat原理解析(一):一个简单的实现
  4. Hibernate4之session核心方法
  5. Gitlab的develop角色的人没有权限无法提交的问题解决方案
  6. app 图标规格参考表
  7. set row count
  8. WPF指南之XAML概述
  9. Mysql数据库---约束类型_mysql数据库的数据类型及约束
  10. mysql获取后一天_mysql获取当前时间,前一天,后一天