HashMap、HashTable和ConcurrentHashMap底层实现有什么区别?

在面试过程中面试官会经常问到HashMapHashTable的底层实现和区别,以下是对其做了简单的总结。

  • HashMap的实现原理:

HashMap是基于hash,底层是由数组加上链表的数据结构。

我们通过put()get()方法来存储和获取对象,当将键值传入put()方法时,它调用键值对应的hashCode()方法来计算hashCode,通过hashCode找到数组的存储位置来存储值对象,HashMap使用链表来解决碰撞问题,当发生冲突时就在数组元素所在链表的表头插入该值;当获取对象时,先通过keyhashCode值定位到数组的位置,遍历该位置的链表,再由equals找到正确的键值,找到满足要求的节点返回。

  • HashTable的实现原理

HashTable的底层也是由数组加上链表的数据结构。HashTable类继承自Dictionary类,实现了MapCloneablejava.io.Serializable
HashTableHashMap中的功能相同。而HashTable所有的操作都是通过synchronized锁保护的。再存储数据时,先获取synchronized锁,通过key的哈希值计算出数组位置来存储值对象。获取对象时,首先也是先获得synchronized锁,通过keyhashCode值定位到数组的位置,遍历该位置的链表,再由equals找到正确的键值,找到满足要求的节点返回。

  • ConcurrentHashMap的实现原理

相比HashMap在多线程环境下不安全和HashTable的效率低下,ConcurrentHashMap 则采用了一种分段锁的技术,ConcurrentHashMap是由Segment数组结构和HashEntry数组结构组成;将存储的数据分成多个Segment,在每一个Segment上有一把锁,当多线程访问容器里不同数据段的数据时,线程间就不会存在锁的竞争,从而提高并发访问的效率。

Segment是一种可重入锁ReentrantLock,在ConcurrentHashMap中扮演锁的角色,HashEntry则用于存储键值对数据。一个ConcurrentHashMap里包含一个Segment数组,Segment的结构和HashMap类似,是一种数组和链表结构,一个Segment里包含一个HashEntry数组,每个HashEntry是一个链表结构的元素,每个Segment守护着一个HashEntry数组里的元素,当对HashEntry数组的数据进行修改时,必须首先获得它对应的Segment锁。

  • 关于HashMapHashTable的区别
  1. HashTable是基于Dictionary类,HashMap是实现了Map接口。
  2. HashTable是同步的线程安全的,每个方法上都加了synchronized关键字。HashMap则不是线程安全的。也可以用collections类的synchronizedMap()方法创建一个线程安全的Map对象。
  3. HashMap中的keyvalue是允许为空的,即HashMap中只有一条可以是空的key,但可以有任意条空的value。而HashTablekeyvalue不允许为空。

原文作者: dgb8901,yinxing

原文链接: https://www.itwork.club/2018/07/13/hashMap-hashTable/

版权声明: 转载请注明出处

为您推荐

体验小程序「简易记账」

关注公众号「特想学英语」

线程池及实现原理