1. Java内部集合结构概览
Java集合由两大接口扩展而来,Collection
,Map
。
Collection
:主要是用来存放一组对象,与数据结构中的线性结构相同。其该接口定义了线性结构的标准,但概念它上是模糊的,因为无法对每个线性结构都制定统一的标准。对此,Collection
下已经预先定义了三个常用的接口List
,Set
,Queue
。
Map
:主要用于存放键值对(key,value)。
线性结构包括了数组,栈,队列,双队列,串,线性表。
2. 如何区分 List,Set,Queue,Map?
List
: 数据有序,可重复。
Set
: 数据无序(根据具体实现区分),不可重复
。
Queue
: 数据按特定的排序规则来确定先后顺序,可重复。Queue
遵循队列标准,先进先出,后进后出。
Map
: 数据不可重复且是无序性
。
无序性
:无序 != 随机,无序性指的是在底层数组中没有根据索引顺序添加数据,而是通过数据的哈希值来决定添加的顺序。
不可重复
:通过数据的哈希值与集合数据中的元素哈希值对比,如果相同则不插入。如果集合中所有元素都不匹配需要插入数据的哈希值,则进行equals()
第二次对比,如果equals()
结果返回true
则不插入,反之。
3. List
3.1 ArrayList
底层存储结构:Object[]
数据可以为空:true
线程是否安全:false
支持随机访问:true
与
LinkedList
相比,ArrayList
的插入删除操作效率低下,插入删除的时间复杂度为O(n - i)
。但随机读取比LinkedList
效率高,时间复杂度为O(1)
。
i
:索引位置,n
:集合长度。
Vector
底层存储结构:Object[]
数据可以为空:true
线程是否安全:true
支持随机访问:true
LinkedList
底层存储结构:双向链表
数据可以为空:true
线程是否安全:false
支持随机访问:false
与 ArrayList
相比,LinkedList
插入删除效率更高,只需移动前后指针就能完成操作。如果在头尾插入元素的话时间复杂度为O(1)
,如果在指定位置插入则时间复杂度为O(i)
。
i
:索引位置
Stack
底层存储结构:Object[]
数据可以为空:true
线程是否安全:true
支持随机访问:true
Stack
是从Vector
扩展而来的,在Vector
基础上增加了操作堆栈的方法。
CopyOnWriteArrayList
底层存储结构:Object[]
数据可以为空:true
线程是否安全:写操作线程安全,读操作可能会出现数据不同步
支持随机访问:true
写操作的同时允许读操作,适用于读多写少的场景。不适合内存敏感以及对实时性要求很高的场景。因为写操作时需要复制一个新的数组,使得内存占用为原来的两倍左右。
4. Set
4.1 HashSet
底层存储结构:HashMap
数据可以为空:true
线程是否安全:false
支持随机访问:false
4.2 LinkedHashSet
底层存储结构:HashMap
数据可以为空:true
线程是否安全:false
支持随机访问:false
底层存储结构还是
HashMap
,只是增加了双向链表,记录了插入顺序,让数据有序性。
4.3 TreeSet
底层存储结构:TreeMap
数据可以为空:false
线程是否安全:false
支持随机访问:false
底层由红黑树实现
5. Queue
5.1 PriorityQueue
底层存储结构:Object[]
数据可以为空:false
线程是否安全:false
5.2 ArrayQueue
底层存储结构:Object[]
数据可以为空:true
线程是否安全:false
5.3 ArrayDeque
底层存储结构:Object[]
数据可以为空:false
线程是否安全:false
性能上优于
LinkedList
,且ArrayDeque
也可实现栈操作。
6. Map
6.1 HashMap
底层存储结构:数组链表
数据可以为空:true
线程是否安全:false
JDK1.8 后解决哈希冲突有了新的实现,当链表的长度大于阈值(默认值:8),则将链表转换成红黑树。
在转换前,会判断数组长度是否小于64,如果小于则先将数组扩容再转换至红黑树。
6.2 HashTable
底层存储结构:数组链表
数据可以为空:false
线程是否安全:true
遗留类,不建议使用。
6.3 LinkedHashMap
底层存储结构:数组链表
数据可以为空:true
线程是否安全:false
LinkedHashMap
继承自HashMap
。不同于HashMap
的是,LinkedHashMap
内部使用了双向链表来记录插入位置,使得LinkedHashMap
是有序的。
7. 总结
使用各个集合前首先需要考虑该集合的底层实现与线程安全,底层实现决定了该集合的性能,线程安全决定了该集合是否适合在高并发情况下使用。
考虑这些后再去选择合适的集合一定会事半功倍!
Bye.