Java集合总结(一):列表和队列
java中的具体容器类都不是从头构建的,他们都继承了一些抽象容器类。这些抽象容器类,提供了容器接口的部分实现,方便具体容器类在抽象类的基础上做具体实现。容器类和接口的关系架构图如下:

虚线框表示接口,有Collection, List, Set, Queue, Deque和Map。
有六个抽象容器类:
- AbstractCollection: 实现了Collection接口,被抽象类AbstractList, AbstractSet, AbstractQueue继承,ArrayDeque也继承自AbstractCollection (图中未画出)。
- AbstractList:父类是AbstractCollection,实现了List接口,被ArrayList, AbstractSequentialList继承。
- AbstractSequentialList:父类是AbstractList,被LinkedList继承。
- AbstractMap:实现了Map接口,被TreeMap, HashMap, EnumMap继承。
- AbstractSet:父类是AbstractCollection,实现了Set接口,被HashSet, TreeSet和EnumSet继承。
- AbstractQueue:父类是AbstractCollection,实现了Queue接口,被PriorityQueue继承。
这些抽象类都提供了相应接口的基础实现,同时定义了一些子类必须重写的抽象方法 ,相当于定义了一个模板,这有点类似于一个设计模式——模板方法模式。
下面主要总结一下上图中具体实现类的一些细节和特性:
ArrayList
内部使用Object数组实现、默认初始大小是10,可手动指定,扩容策略是 newCapacity = oldCapacity + (oldCapacity >> 1),
即每次增大到原来的1.5倍,但不会小于最小值,最大容量是Integer.MAX_VALUE,即0x7fffffff。扩容时将一个新建一个数组将原来数组的内容复制过去。
没用泛型数组E[]原因个人猜测是因为java中的泛型是在jdk1.5才开始支持的,在这之前都用的Object,为了保持向前的兼容性不得不这么做,jdk1.6中新增的ArrayDeque内部就是泛型数组E[]。
LinkedList
内部使用链表实现,可以用作队列(Queue),队列两端都可以操作,尾部添加,头部查看和删除。也可以用作双端队列(Deque)(双向链表)(双向遍历、可以实现栈的功能)。
内部只维护头和尾结点,构造方法不能指定大小,按需分配空间。
性能
- 不可以随机访问,必须从头或尾开始查找,效率为O(N/2)(用了二分法)
- 按照内容查找效率为O(N/2)
- 两端添加删除效率为O(1)
- 中间插入删除先定位 ,效率为O(n),但插入或者删除本身效率很高,为O(1)
ArrayDeque
这是jdk1.6新增的一个类。内部维护一个泛型数组E[],使用head和tail两个int索引表示链表头和尾(其中tail指向下一个空位),使得物理上简单的从头到尾的数组变成了逻辑上循环的数组,可以作为链表使用。默认初始数组大小是16,扩容策略是乘以2
- 如果head和tail相同,则数组为空,长度为0。
- 如果tail大于head,则第一个元素为elements[head],最后一个为elements[tail-1],长度为tail-head,元素索引从head到tail-1。
- 如果tail小于head,且为0,则第一个元素为elements[head],最后一个为elements[elements.length-1],元素索引从head到elements.length-1。
- 如果tail小于head,且大于0,则会形成循环,第一个元素为elements[head],最后一个是elements[tail-1],元素索引从head到elements.length-1,然后再从0到tail-1。
可以通过构造方法指定初始数组大小numElements,但是实际的大小是:
- 如果numElements小于MIN_INITIAL_CAPACITY,则分配的数组长度就是MIN_INITIAL_CAPACITY,它是一个静态常量,值为8。
- 在numElements大于等于8的情况下,分配的实际长度是严格大于numElements并且为2的整数次幂的最小数。比如,如果numElements为10,则实际分配16,如果numElements为32,则为64。
使用2的幂次方是为了保证
public void addLast(E e) {
if (e == null)
throw new NullPointerException();
elements[tail] = e;
if ( (tail = (tail + 1) & (elements.length - 1)) == head)
doubleCapacity();
}
中(tail + 1) & (elements.length - 1)能定位到正确下一个位置tail,比如说,如果elements.length为8,则(elements.length - 1)为7,二进制为0111,对于负数-1,与7相与,结果为7,对于正数8,与7相与,结果为0,都能达到循环数组中找下一个正确位置的目的。
扩容之后会重新排列数组,head是0,tail是当前元素数。
性能
- 在两端添加、删除元素的效率很高,动态扩展需要的内存分配以及数组拷贝开销可以被平摊,具体来说,添加N个元素的效率为O(N)。
- 根据元素内容查找和删除的效率比较低,为O(N)。
简单总结:
与ArrayList和LinkedList不同,ArrayDeque没有索引位置的概念,不能根据索引位置进行操作。
ArrayDeque和LinkedList都实现了Deque接口,应该用哪一个呢?如果只需要Deque接口,从两端进行操作,一般而言,ArrayDeque效率更高一些,应该被优先使用,不过,如果同时需要根据索引位置进行操作,或者经常需要在中间进行插入和删除,则应该选LinkedList。
Java集合总结(一):列表和队列的更多相关文章
- Java集合框架之LinkedList-----用LinkedList模拟队列和堆栈
LinkedList的特有方法: (一)添加方法 addFisrt(E e):将指定元素插入此列表的开头.//参数e可以理解成Object对象,因为列表可以接收任何类型的对象,所以e就是Object对 ...
- java集合详解(附栈,队列)
1 集合 1.1 为什么会出现集合框架 [1] 之前的数组作为容器时,不能自动拓容 [2] 数值在进行添加和删除操作时,需要开发者自己实现添加和删除. 1.2 Collection接口 1.2.1 C ...
- Java笔记(六)列表和队列
列表和队列 一)ArrayList 1.基本原理 ArrayList是一个泛型容器.内部会有一个数组elementData,一般会有预留空间 有一个整数记录实际的元素个数. private trans ...
- Java 集合深入理解(10):Deque 双端队列
点击查看 Java 集合框架深入理解 系列, - ( ゜- ゜)つロ 乾杯~ 什么是 Deque Deque 是 Double ended queue (双端队列) 的缩写,读音和 deck 一样,蛋 ...
- Java 集合深入理解(9):Queue 队列
点击查看 Java 集合框架深入理解 系列, - ( ゜- ゜)つロ 乾杯~ 今天心情不太好,来学一下 List 吧! 什么是队列 队列是数据结构中比较重要的一种类型,它支持 FIFO,尾部添加.头部 ...
- Java 集合 散列表hash table
Java 集合 散列表hash table @author ixenos 摘要:hash table用链表数组实现.解决散列表的冲突:开放地址法 和 链地址法(冲突链表方式) hash table 是 ...
- Java集合(二):List列表
在上一节中,介绍了Java集合的总体情况.从这节開始,将介绍详细的类.这里不单单介绍类的使用方法.还会试图从源代码的角度分析类的实现.这一节将介绍List接口及实现类.即列表中的链表LinkedLis ...
- Java集合--阻塞队列及各种实现的解析
阻塞队列(Blocking Queue) 一.队列的定义 说的阻塞队列,就先了解下什么是队列,队列也是一种特殊的线性表结构,在线性表的基础上加了一条限制:那就是一端入队列,一端出队列,且需要遵循FIF ...
- 关于Java集合类库中的几种常用队列
Java中几种常用的队列 阻塞队列与普通队列的区别在于,当队列是空的时,从队列中获取元素的操作将会被阻塞,或者当队列是满时,往队列里添加元素的操作会被阻塞.试图从空的阻塞队列中获取元素的线程将会被阻塞 ...
- Java 集合框架
Java集合框架大致可以分为五个部分:List列表,Set集合.Map映射.迭代器.工具类 List 接口通常表示一个列表(数组.队列.链表 栈),其中的元素 可以重复 的是:ArrayList 和L ...
随机推荐
- SAS学习笔记23 线性回归、多元回归
线性回归 由样本资料计算的回归系数b和其他统计量一样,存在抽样误差,因此,需要对线性回归方程进行假设检验 1.方差分析 2.t检验 相关系数的假设检验 相关系数(correlation coeffic ...
- mybatis相关知识积累
mybatis Statement Statement对象用于将 SQL 语句发送到数据库中. 实际上有三种 Statement 对象,它们都作为在给定连接上执行 SQL语句的包容器: Stateme ...
- 第四讲,数据目录表之导入表,以及IAT表
一丶IAT(地址表) 首先我们思考一个问题,程序加载的时候会调用API,比如我们以前写的标准PE 那么他到底是怎么去调用的? 它会Call 下边的Jmp位置 而Jmp位置则是对一个全局变量取内容. 看 ...
- Java Web 深入分析(1)B/S架构概述
B/S结构即浏览器和服务器结构.它是随着Internet技术的兴起,对C/S结构的一种变化或者改进的结构.在这种结构下,用户工作界面是通过WWW浏览器来实现,极少部分事务逻辑在前端(Browser)实 ...
- Xamarin开发综述
https://blog.csdn.net/qq_41647999/article/details/84844357 一. 前言这十来天对Xamarin的学习踩了很多的坑,说来也是一把心酸泪,下面为大 ...
- ulimit用法
ulimit -a:显示当前所有的资源限制 -c:core文件大小 -f:设置创建文件的最大值 -n:设置内核可以同时打开的文件描述符的最大值 -p:设置管道缓冲区的最大值 -s:设置堆栈的最大值 - ...
- JAVA基于PDF box将PDF转为图片
在一项目中用到,本身我是.NET的,团队中有用到JAVA,故此我处理这个功能,记录以下备用. 1.引用:fontbox-2.0.16.jar.pdfbox-app-2.0.16.jar 版本一定要正确 ...
- C# 中 Linq 操作 DataTable
方法一:更简洁 Console.WriteLine(dt.Rows.OfType<DataRow>().First(x => x.Field<string>(" ...
- KVM之配置桥接网卡
配置桥接网卡 添加桥接网卡br0,注释掉已有的eth0配置 [root@ubuntu01 ~]# vi /etc/network/interfaces # This file describes th ...
- 【Zookeeper】实现哨兵机制(选举策略)
一.Master选举使用场景及结构 二.代码实现 2.1 Maven依赖信息 2.2 IndexController 2.3 MyApplicationRunner 2.4 ElectionMaste ...