学习目标
-
hash冲突的解决办法有哪几种
-
HashTable、hashmap、CHM三者之间的区别
-
HashMap的默认长度是多少?默认扩容因子是多少?
-
HashMap它是怎么解决hash冲突的
-
HashMap为什么扩容是2的幂次方
-
谈一下HashMap中put是如何实现的?
-
谈一下hashMap中什么时候需要进行扩容,扩容resize()又是如何实现的?
-
谈一下hashMap中get是如何实现的?
-
为什么是16?为什么必须是2的幂?如果输入值不是2的幂比如10会怎么样?
-
HashMap和HashTable的区别
-
hashmap中的扰动函数有什么作用
-
hashmap的底层数据结构(1.7和1.8版本)
-
hashmap为什么是线程不安全的(1.7和1.8版本)
-
在什么情况下hashmap的链表会转化成红黑树
-
HashMap的key可以为null吗?CHM呢?
第1章 前置知识
1、Hash表
Hash函数:MD5、SHA
Hash表:通过hash函数来计算数据位置的数据结构
HashMap通过数组去存储
2、Hash冲突
多个不同的key通过hash函数运算之后落在同一个数组下标的位置。
解决方案:
-
ThreadLocal解决方案:线性探索(开发寻址法)
-
HashMap解决方案:链式地址法
-
再Hash法(通过多个hash函数)
3、锁粒度
-
hashtable:是对整个数组加锁,两个线程对同一个hashtable进行操作时,只可能有一个线程进行put。
-
1.7CHM:对数组中的每个segment加锁,不同线程对同一个CHM进行操作时,如果hash计算没有落在同一个segment时,就可以同时操作。每个segment里面存的也是一个16个长度的数组,然后数组里面存链表
-
18CHM:对数组中的每个node加锁,不同线程对同一个CHM进行操作时,如果hash计算没有落在同一个node时,就可以同时操作。每个node里面存的是存链表或红黑树。
第2章 HashMap
2.1 从new说起
HashMap hashMap=new HashMap(5);
public HashMap(int initialCapacity, float loadFactor) {
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal initial capacity: " +
initialCapacity);
if (initialCapacity > MAXIMUM_CAPACITY)
initialCapacity = MAXIMUM_CAPACITY;
if (loadFactor <= 0 || Float.isNaN(loadFactor))
throw new IllegalArgumentException("Illegal load factor: " +
loadFactor);
this.loadFactor = loadFactor;
this.threshold = tableSizeFor(initialCapacity); //代表hashMap的容量大于这个的时候会进行resize操作
}
不管传多大的容量,容量都是最靠近设置值的2的幂次方,且大于传入值
2.2 右移左移补充
<<表示左移移,不分正负数,低位补0;
注:以下数据类型默认为byte-8位
左移时不管正负,低位补0
正数:r = 20 << 2
20的二进制补码:0001 0100
向左移动两位后:0101 0000
结果