ava容器类4:Queue深入解读

1594931-293dba23ebc504c2

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中接口有变动,但是大概含义相似)

image

在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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/439624.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Waymo离线点云序列3D物体检测网络 (3D Auto Labeling): Offboard 3D Object Detection from Point Cloud Sequences

本文介绍一篇Waymo基于点云序列的3D物体检测网络&#xff1a;3D Auto Labeling&#xff0c;论文已收录于CVPR 2021。 这里重点是理解本文提出的 Object-centric Auto Labeling。 论文链接为&#xff1a;https://arxiv.org/abs/2103.05073 2021-09-02补充&#xff1a;本文作者…

【OpenJ_Bailian - 2711 】 合唱队形(dp,枚举中间顶点)

题干&#xff1a; N位同学站成一排&#xff0c;音乐老师要请其中的(N-K)位同学出列&#xff0c;使得剩下的K位同学不交换位置就能排成合唱队形。 合唱队形是指这样的一种队形&#xff1a;设K位同学从左到右依次编号为1, 2, …, K&#xff0c;他们的身高分别为T1, T2, …, TK&…

Waymo自动驾驶数据集介绍与使用教程

本文将对Waymo自动驾驶数据集&#xff08;Waymo Open Dataset&#xff09;进行介绍。 论文链接为&#xff1a;https://arxiv.org/abs/1912.04838v7 项目链接为&#xff1a;https://github.com/waymo-research/waymo-open-dataset 数据集链接为&#xff1a;https://waymo.com…

Java 并发基础——线程安全性

线程安全&#xff1a;多个线程访问某个类时&#xff0c;不管运行时环境采用何种调度方式或者这些线程将如何交替执行&#xff0c;并且在主调代码中不需要任何额外的同步或协调&#xff0c;这个类都能表现出正确的行为&#xff0c;那么久称这个类是线程安全的。 在线程安全类中封…

详解一阶段3D物体检测网络 SE-SSD: Self-Ensembling Single-Stage Object Detector From Point Cloud

本文介绍一篇一阶段的3D物体检测网络&#xff1a;SE-SSD&#xff0c;论文已收录于 CVPR 2021。 这里重点是理解本文提出的 Consistency Loss 、Orientation-Aware Distance-IoU Loss、Shape-Aware Data Augmentation。 论文链接为&#xff1a;https://arxiv.org/pdf/2104.0980…

【POJ - 3744】Scout YYF I(概率dp,矩阵快速幂优化dp)

题干&#xff1a; 题目大意&#xff1a; 在一条不满地雷的路上&#xff08;无限长&#xff09;&#xff0c;你现在的起点在1处。在N个点处布有地雷&#xff0c;1<N<10。地雷点的可能坐标范围&#xff1a;[1,100000000]. 每次前进p的概率前进一步&#xff0c;1-p的概率…

详解3D点云分割网络 Cylindrical and Asymmetrical 3D Convolution Networksfor LiDAR Segmentation

本文介绍一篇3D点云分割网络&#xff1a;Cylinder3D&#xff0c;论文已收录于 CVPR 2021。 这里重点是理解本文提出的 Cylindrical Partition 和 Asymmetrical 3D Convolution Network。 论文链接为&#xff1a;https://arxiv.org/pdf/2011.10033.pdf 项目链接为&#xff1a;…

Java中泛型Class《T》、T与Class《?》

一.区别 单独的T 代表一个类型 &#xff0c;而 Class<T>代表这个类型所对应的类&#xff0c; Class<&#xff1f;>表示类型不确定的类 E - Element (在集合中使用&#xff0c;因为集合中存放的是元素)T - Type&#xff08;Java 类&#xff09;K - Key&#xff08;…

【CodeForces - 701D】As Fast As Possible(二分,模拟,数学公式)

题干&#xff1a; On vacations n pupils decided to go on excursion and gather all together. They need to overcome the path with the length l meters. Each of the pupils will go with the speed equal to v1. To get to the excursion quickly, it was decided to r…

自动驾驶3D物体检测研究综述 3D Object Detection for Autonomous Driving: A Survey

本文介绍一篇最新的自动驾驶3D物体检测研究综述&#xff08;2021年6月份发布&#xff09;&#xff0c;来源于中国人民大学&#xff0c;论文共26页&#xff0c;99篇参考文献。 论文链接为&#xff1a;https://arxiv.org/pdf/2106.10823.pdf 0. Abstract 自动驾驶被看作是避免人…

【CodeForces - 705C】Thor(模拟,STLset优化链表)

题干&#xff1a; Thor is getting used to the Earth. As a gift Loki gave him a smartphone. There are n applications on this phone. Thor is fascinated by this phone. He has only one minor issue: he cant count the number of unread notifications generated by …

Java中接口的多继承

我们知道Java的类只能继承一个类&#xff0c;但可以实现多个接口。但是你知道么&#xff1f;Java中的接口却可以继承多个接口。本文就来说一说Java中接口的多继承。 进入主题之前&#xff0c;先扩展一下。Java为什么只支持单继承呢&#xff1f; 我们不妨假设Java支持多继承&a…

详解基于IMU/GPS的行人定位: IMU/GPS Based Pedestrian Localization

本文介绍一篇使用 IMU/GPS 数据融合的行人定位论文&#xff0c;这里重点是理解本文提出的 Stop Detection 和 GPS Correction。 论文地址为&#xff1a;https://www.researchgate.net/publication/261452498_IMUGPS_based_pedestrian_localization 1. Introduction 低成本的 …

每次maven刷新jdk都要重新设置

pom.xml <java.version>17</java.version> 改为<java.version>1.8</java.version>

【CodeForces - 706D】Vasiliy's Multiset(01字典树)

题干&#xff1a; Author has gone out of the stories about Vasiliy, so here is just a formal task description. You are given q queries and a multiset A, initially containing only integer 0. There are three types of queries: " x" — add integer …

LaTeX常用数学符号总结

本文汇总了在使用LaTeX中常用的数学符号&#xff0c;相关下载资源为&#xff1a;139分钟学会Latex&#xff08;免积分下载&#xff09;。 文章目录1. 希腊字母2. 集合运算符3. 数学运算符4. 三角符号、指数符号、对数符号5. 积分、微分、偏微分6. 矩阵和行列式7. 基本函数、分段…

基本类型优先于装箱基本类型

基本类型与包装类型的主要区别在于以下三个方面&#xff1a; 1、基本类型只有值&#xff0c;而包装类型则具有与它们的值不同的同一性&#xff08;identity&#xff09;。这个同一性是指&#xff0c;两个引用是否指向同一个对象&#xff0c;如果指向同一个对象&#xff0c;则说…

【CodeForces - 827A】String Reconstruction(并查集合并区间,思维)

题干&#xff1a; Ivan had string s consisting of small English letters. However, his friend Julia decided to make fun of him and hid the string s. Ivan preferred making a new string to finding the old one. Ivan knows some information about the string s. …

详解自动驾驶仿真框架OpenCDA: An Open Cooperative Driving Automation Framework Integrated with Co-Simulation

本文介绍一款同时支持协同驾驶开发与测试、自动驾驶全栈开发 和 CARLA-SUMO联合仿真的开源框架 OpenCDA&#xff0c;论文已收录于 ITSC 2021。主要feature有&#xff1a; 支持CARLA-SUMO联合仿真&#xff0c;CARLA端主管环境渲染、传感器模拟、车辆动力&#xff0c;Sumo端主管…

JavaMonitor 监视器

为什么wait(), notify()和notifyAll()必须在同步方法或者同步块中被调用&#xff1f; 当一个线程需要调用对象的wait()方法的时候&#xff0c;这个线程必须拥有该对象的锁&#xff0c;接着它就会释放这个对象锁并进入等待状态直到其他线程调用这个对象上的notify()方法。同样的…