前言
前一阵子,manager随口问了我这样一个问题,我想从Map中按顺序取出数据,那我应该用哪一个实现类呀?当时我感觉答案就在我的脑边,但是就是想不起来了。从这一点看,还是需要温故而知新的。
最近一直在看《码出高效——Java开发手册》这本书,确实是一本好书值得推荐,知识点说的十分通俗易懂,本篇文章,正是参考这本书的。
正文
首先呢,如果想要解决上面的问题,可以使用两种集合,一种是LinkedHashMap,另一种是TreeMap,两种的相同与不同之处,我会在下面说到。
集合中的顶层接口,最重要的就是Collection和Map了。
原来我听大学老师说过这样一句话,最懂集合的就是迭代器了(Map集合除外,因为Map是一个特殊的集合)。所以Collection接口实现了Iterable接口,让继承了Collection接口的接口,具有可以迭代的能力。
Collection 一共有三个儿子,分别是 List,Set, 和Queue。
List集合
list集合的概念与我们最开始接触的数组相类似,有明确的第一个与最后一个元素,我们通过迭代器,可以拿到和我们插入的顺序的值,一样的结果,list中我们最常用的就是ArrayList和LinkedList了。list在初始化的时候,建议是要在构造函数中给出长度的。避免扩容可能带来的效率问题
1.ArrayList
底层通过数组进行实现,但是数组在初始化的时候是需要给出长度的,为啥ArrayList不用呢,其实ArrayList在初始化的时候,默认长度为10,但是他会随着数据的增多进行扩容。每一次扩容是把原来的长度右移一位(大概就是原来长度的一半),举个简单的例子,原来的长度为10,转化为2进制就是1010,右移一位就是101,然后再转化为十进制就是5。为什么这里特别强调是右移一位,而不是1/2呢,因为如果原始长度是奇数,会让人感到困惑。
ArrayList具有查询速度快,但是插入和删除速度相对较慢,想象一下这样的场景,我们有一个size为10的的list,我们把第二个位置上的值删掉,那么后面所有的数据都需要移动。
2.LinkedList
LinkedList使用的是双向链表(在Java中所有链表的实现,使用的都是双向链表),相比于ArrayList,插入与删除速度较快,因为只需要把指向上一个引用的地址和指向下一个引用的地址进行修改即可,但是相对随机访问速度较慢。在内存中,利用率更高,因为不需要一整块的内存。
Set集合
Set集合中不允许出现相同的元素,很多人都不明白为什么,其实Set集合的本质是Map只不过他的Value放置的是一个静态的对象。这样也就解释通了为什么key不能相同了。Set只能使用迭代器,而不能通过index去get具体位置上的元素,也是因为这个原因。Set中最常用的为HashSet,LinkedHashSet,以及TreeSet。其中LinkedHashSet和TreeSet在插入后的顺序,仍然是有序的。
Queue集合
Queue(队列),是先进先出的一个特殊的线性表,根据这一种特性,经常被用作数据缓存区,现在比较流行的MQ(消息队列)也是根据这一特性。
Map集合
Map是以key,value键值对组成的哈希结构。Map集合和Collection中关系最密切的要属Set了(之前在将Set的时候,也有说过)我们通过keySet()方法获取到所有的key,返回的是一个set集合,可以通过values拿到所有的value,还可以通过entrySet拿到所有的键值对。所有Map集合使用起来,灵活度非常的高。
最开始的时候Map集合比较出名的是Hashtable,他是线程安全的,采用了锁,来保护数据的安全性,但是同时会带来效率底下的问题,于是便被放弃了。
后来出现了大名鼎鼎的HashMap,他放弃了线程安全,但是解决了效率问题,我们可以在局部方法和不用考虑线程是否安全的情况下,使用它。但是线程不安全还是有很大风险,这个问题还得需要解决。多说一点HashMap默认长度为16,还有一个属性叫做填充比例,默认为0.75。如果长度超过了长度*填充比例,那么就得需要扩容了,扩容长度为原来的两倍。
于是便创造出来了ConcurrentHashMap,他是线程安全性和效率最好的一个平衡,多并发情况优先考虑。
回到写这个博文,最开始的问题LinkedHashMap与TreeMap都是可以保证插入数据顺序的。LinkedHashMap对于插入删除数据的速度快,TreeMap的优势则在于查找数据的时候,底层为红黑树实现,可以根据业务需求使用不同的数据集合。
以下是Map集合总结的表格
Map集合类 | Key | Value | Super | JDK | 说明 |
---|---|---|---|---|---|
HashTable | 不允许为空 | 不允许为空 | AbstractMap | 1.0 | 线程安全(过时) |
ConcurrentHashMap | 不允许为空 | 不允许为空 | AbstractMap | 1.5 | 锁分段技术或CAS |
TreeMap | 不允许为空 | 允许为空 | AbstractMap | 1.2 | 线程不安全有序 |
HashMap | 允许为空 | 允许为空 | AbstractMap | 1.2 | 线程不安全(高并发存在思索问题) |
总结
最后以一个具体的表格进行总结
集合类型 | 描述 |
---|---|
ArrayList | 一种可以动态增长和缩减的索引序列 |
LinkedList | 一种可以在任何位置进行高效的插入和删除操作的有序序列 |
ArrayDeque | 一种用循环属猪实现的双端队列 |
HashSet | 一种没有重复元素的无序集合 |
TreeSet | 一种有序集 |
EnumSet | 一种包含枚举类型的值 |
LinkedHashSet | 一种可以记住插入次序的集合 |
PriorityQueue | 一种允许高效删除最小元素的集合 |
HashMap | 一种存储键/值关联的数据结构 |
TreeMap | 一种键值有序排列的映射表 |
EnumMap | 一种键值属于枚举的映射表 |
LinkedHashMap | 一种可以记住插入次序的映射表 |
WeakHashMap | 一种如果值没有用的情况下被GC的映射表 |
IdentityHashMap | 一种用==而不是用equals比较键值的映射表 |
网友评论