Bootstrap

HashMap HashTable ConCurrentHashMap三者的区别

HashMap HashTable ConCurrentHashMap三者的区别

  1. 底层实现原理

HashMap 在Jdk1.7之前底层实现为数组+链表,通过哈希算法将元素的键(key)映射到数组槽位(bucket)中,如果多个键映射同一个槽位,它们会以链表的形式存储在同一个槽位上

HashTable 底层实现为数组+链表,数组为主体,链表是为了解决哈希冲突

ConcurrentHashMap 在jdk1.8之前采用的是分段的数组+链表,一个ConcurrentHashMap包含一个Segment数组,而一个Segment(扮演锁的角色)里包含一个HashEntry数组(用于存储键值对),每个HashEntry是一个链表结构的元素,因此遍历元素时较慢

在jdk1.8之后,采用数组+链表/红黑树,利用红黑树优化了之前的链表结构,一句话概述也就是:在利用在头结点加锁来保证线程安全,锁的粒度相比于Segment更小,且发生冲突和加锁的频率更低,并发操作的性能也就大大提升,时间复杂度也由O(n)->O(logn)

  1. 能不能存null键,null值

HashMap 可以存null键值对,只能有一个null键,因为键重复的话添加的时候会自动覆盖,可以有多个null值
HashTable 不可以存储null键值

  1. 扩容机制

HashMap 默认初始量为16,每次扩容2倍,如果插入元素后链表长度大于8的话,再判断数组长度是否大于64,如果大于64就将链表转为红黑树,反之扩容数组

  1. 线程安全

HashMap是线程不安全的,效率高一点

HashTable和ConcurrentHashMap线程安全,其中HashTable是将方法整体上锁同步,因此当多个线程进入的时候,需要等待锁内方法执行结束,效率较低

而ConcurrentHashMap在jdk1.8之前是利用分段锁,每个数组都分段上锁,在jdk1.8之后主要通过volatile + CAS 或者 synchronized实现线程安全

;