源码分析之五种Map容器的区别

  • 1、Java中的Map容器概述
  • 2、HashMap容器
  • 3、Hashtable容器
  • 4、ConcurrentHashMap容器
  • 5、LinkedHashMap容器
  • 6、TreeMap容器

1、Java中的Map容器概述

      Map是一种存储key-value(键值对)的容器,在Java中,常见的Map接口的实现类有五种,分别是HashMap、Hashtable、ConcurrentHashMap、LinkedHashMap、TreeMap。五种容器的关系如下图:

两个容器不能实现跨主机连通 不同容器_两个容器不能实现跨主机连通


      注意不能把:hash与map两个概念混为一谈,然而map是用于存储key-value的虚拟容器,按照key的hash值将节点散列到一个table数组(也称hash表)的table[i](也称hash桶)中。

2、HashMap容器

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

两个容器不能实现跨主机连通 不同容器_两个容器不能实现跨主机连通_02


特点:

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

3、Hashtable容器

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

两个容器不能实现跨主机连通 不同容器_Java_03


特点:

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

4、ConcurrentHashMap容器

      Java中的ConcurrentHashMap底层同样是使用一个table数组存放节点,使用链表解决hash冲突(多个元素的hash值散列到同一个table[i]中)的问题。在JDK 1.8前的版本中引入段的概念,使用RententLock锁,并且分段锁(对每个段分别设置一个锁),相比于Hashtable锁整个容器,并发操作时,效率提高了不少。

      在JDK 1.8的时候,又取消了段的概念,重新使用synchronized关键字(同步代码块)。不过每次锁住的对象的是需要修改的table[i](hash桶),并且在各大方法中尽量减少了同步代码块中的代码量,从而减少了锁的粒度,并发操作时,效率提高了不少。在扩容时,支持多个线程同时进行扩容(并发扩容)。

JDK1.7:

两个容器不能实现跨主机连通 不同容器_面试_04


JDK1.8:

两个容器不能实现跨主机连通 不同容器_Java_05


特点:

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

5、LinkedHashMap容器

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

两个容器不能实现跨主机连通 不同容器_java_06


特点:

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

6、TreeMap容器

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

两个容器不能实现跨主机连通 不同容器_Map_07


特点:

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