一、HashMap
·HashMap是基于哈希表的Map接口实现的,以key-value的存储形式存在。由于HashMap的实现不是同步的,这意味着它不是线程安全的。他的key,value都可以为null,除此之外HashMap中的映射不是有序的。
·在jdk1.8之前HashMap由数组+链表组成,数组的HashMap的主体,链表主要是为了解决哈希冲突(两个对象调用的hashCode方法计算的哈希值,经哈希函数算出来的地址被别的元素占用)。jdk1.8之后解决哈希冲突有了较大的变化,当链表长度大于阈值或者红黑树的边界值(默认为8),并且当前数组的长度大于64时,此时此索引位置上的所有数据改为使用红黑树存储。

二、HashMap与HashTable的区别
HashMap和HashTable都实现了Map接口,但是决定用哪一个之前先弄清他们之间的区别,主要区别有:线程安全,同步以及速度。
1.HashMap和HashTable几乎可以等价,但是HashMap是不能同步(synchronized)的并且可以接受key和value是null值的。HashTable不行。
2.由于HashTable是synchronized的,这意味着HashTable是线程安全的,多个线程可以共享一个HashTable
3.由于HashTable是线程安全的,所以在单线程环境下比HashMap慢
4.HashMap不能保证随着时间的推移Map中的元素次序是不变的
三、CorrentHashMap
CorrentHashMap可以说是HashMap的升级版,CorrentHashMap是线程安全的,但是与HashTable实现线程安全的方式不同。
HashTable是通过对hash表结构进行锁定,是阻塞式的,当一个线程占有这个锁时,其他线程必须阻塞等待其释放锁。CorrentHashMap是采用分离锁的方式,它并没有对整个哈希表进行锁定,而是局部锁定,也就是说当一个线程占有这个局部锁时,不影响其他线程对哈希表的其他地方访问。
CorrentHashMap对读操作没有加锁(但是使用了 volatile 保证从内存读取结果), 只对写操作进行加锁.
加锁的方式仍然 是是用 synchronized, 但是不是锁整个对象, 而是 "锁桶" (用每个链表的头结点作为锁对象), 大大降 低了锁冲突的概率.
充分利用 CAS 特性. 比如 size 属性通过 CAS 来更新. 避免出现重量级锁的情况.
优化了扩容方式: 化整为零 发现需要扩容的线程, 只需要创建一个新的数组, 同时只搬几个元素过去. 扩容期间, 新老数组同时存在. 后续每个来操作 ConcurrentHashMap 的线程, 都会参与搬家的过程. 每个操作负责搬运一小 部分元素. 搬完最后一个元素再把老数组删掉. 这个期间, 插入只往新数组加. 这个期间, 查找需要同时查新数组和老数组
本文介绍了HashMap的基本概念,包括其非线程安全特性,哈希冲突的处理方式。重点比较了HashMap与线程安全的HashTable和ConcurrentHashMap在线程同步、性能及实现方式上的差异。
382

被折叠的 条评论
为什么被折叠?



