Java中的常见五种map容器源码分析总结(HashMap、Hashtable、ConcurrentHashMap、LinkedHashMap、TreeMap)

  断断续续写了半个月,今天终于把TreeMap容器中的红黑树搞定了,现在来水一篇又快又短Java Map容器总结博客 😂😂。

注明:本篇博客不会涉及容器的源码什么的,主要是总结各个map容器的底层实现特点、主要运用场景。如果你需要详细了解更多关于Java中的map容器实现的细节,文末会提供我前面写的源码分析的博客链接,欢迎阅读。

一、Java中的Map容器概述

  Map是一种存储key-value键值对)的容器,在Java中,常见的Map接口的实现类有五种,分别是HashMapHashtableConcurrentHashMapLinkedHashMapTreeMap。五种容器的关系如下图:
在这里插入图片描述
  顺带一提,貌似有不少人觉得map就是hashmaphashmap就是map,把hashmap两个概念混为一谈。然而map是用于存储key-value的虚拟容器,按照key的hash值将节点散列到一个table数组(也称hash表)的table[i](也称hash桶)中。等你看完TreeMap的底层数据结构就会发现,不通过key.hash值,也可以实现map容器

二、HashMap容器

1、HashMap概述

  Java中的HashMap底层使用一个table数组存放节点,使用链表(JDK 1.8新增红黑树)解决hash冲突(多个元素的hash值散列到同一个table[i]中)的问题。

2、HashMap数据结构示意图

在这里插入图片描述

3、HashMap特点

  • ①、存取高效,不支持并发读写操作(没有引入锁任何机制)
  • ②、table数组的长默认是16,并且每次扩容为原来的2倍(长度总是保持为2的次幂,方便hash值求余)
  • ③、支持key、value为null的键值对插入

4、HashMap源码分析链接

Java容器之HashMap源码分析(妈妈再也不用担心我不懂HashMap了)

三、Hashtable容器

1、Hashtable概述

  Java中的Hashtable底层同样是使用一个table数组存放节点,使用链表解决hash冲突(多个元素的hash值散列到同一个table[i]中)的问题。不过引入了锁机制(通过synchronized关键字,锁为this,每次锁住整个容器),支持并发操作。

2、Hashtable数据结构示意图

在这里插入图片描述

3、Hashtable特点

  • ①、写入、删除效率相对较低。引入锁机制,通过synchronized关键字修饰方法(同步方法),锁对象为this,每次锁住整个容器,锁的粒度太大。
  • ②、table数组的长默认是11,并且每次扩容为原来的2倍 + 1
  • ③、不支持key、value为null的键值对插入

4、Hashtable源码分析链接

Java容器之Hashtable源码分析(关于Hashtable的这些细节你可能还不知道)

四、ConcurrentHashMap容器

1、ConcurrentHashMap概述

  Java中的ConcurrentHashMap底层同样是使用一个table数组存放节点,使用链表解决hash冲突(多个元素的hash值散列到同一个table[i]中)的问题。在JDK 1.8前的版本中引入段的概念,使用RententLock锁,并且分段锁(对每个段分别设置一个锁),相比于Hashtable锁整个容器,并发操作时,效率提高了不少。
  在JDK 1.8的时候,又取消了段的概念,重新使用synchronized关键字(同步代码块)。不过每次锁住的对象的是需要修改的table[i]hash桶),并且在各大方法中尽量减少了同步代码块中的代码量,从而减少了锁的粒度,并发操作时,效率提高了不少。在扩容时,支持多个线程同时进行扩容(并发扩容)。

2、ConcurrentHashMap数据结构示意图

在这里插入图片描述
在这里插入图片描述

3、ConcurrentHashMap特点

  • ①、写入、删除效率相比与Hashtable容器较高。引入锁机制,通过synchronized关键字(同步代码块),锁对象为即将修改的table[i](hash桶),锁的粒度小。
  • ②、table数组的长默认是16,并且每次扩容为原来的2倍(长度总是保持为2的次幂,方便hash值求余)
  • ③、不支持key、value为null的键值对插入

4、ConcurrentHashMap源码分析链接

Java容器之ConcurrentHashMap源码分析(JDK 1.7与JDK 1.8对比)

五、LinkedHashMap容器

1、LinkedHashMap概述

  Java中的LinkedHashMapHashMap的子类,也可以说是对HashMap的封装。对外展示的是一个双向链表,链表中的元素顺序,就是插入节点的顺序。

2、LinkedHashMap数据结构示意图

在这里插入图片描述

3、LinkedHashMap特点

  • ①、LinkedHashMap是对HashMap的进一步封装,所以实现细节基本一致
  • ②、对外展示为双向链表,链表节点中的顺序为插入时的顺序(其实也可以修改为访问顺序)

4、LinkedHashMap源码分析链接

Java容器之LinkedHashMap源码分析(看看确定不点进来?进来真不点?)

六、TreeMap容器

1、TreeMap概述

  Java中的TreeMap容器底层是通过维护一棵红黑树来存储key-value节点,与hash没有任何关系。树中的节点按照key的大小排序,可以手动指定key的比较器comparator

2、TreeMap数据结构示意图

在这里插入图片描述

3、TreeMap特点

  • ①、读写高效,查找的复杂度在O(log2n)级别。(不支持并发读写,为引入锁)
  • ②、节点按照key升序排列,可指定key的比较器comparator
  • ③、不支持key为null的key-value插入

4、TreeMap源码分析链接

Java容器之TreeMap源码分析(附红黑树调整图解)

七、总结

  HashMapLinkedHashMapHashtableConcurrentHashMap这四个都是通过table数组,并结合hash散列存放节点,前两者不支持并发读写,效率较高,后两者支持并发,并且ConcurrentHashMap的效率更高些。TreeMap容器通过红黑树存储key-value节点,节点按照key的大小排序,查找、插入比较高效,时间复杂度在O(log2n)级别。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章