1 、为什么hashmap 扩容是2的倍数?
hashmap put 的时候直接去key的hash值方法
public V put(K key, V value) {
return putVal(hash(key), key, value, false, true);
}
key的hashcode 异或 key的hashcode的位移
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
jdk 1.7 取数组角标位置
static int indexFor(int h, int length) {
return h & (length-1);
上述代码也相当于对length求模。 注意最后return的是h&(length-1)。如果length不为2的幂,比如15。那么length-1的2进制就会变成1110。在h为随机数的情况下,和1110做&操作。尾数永远为0。那么0001、1001、1101等尾数为1的位置就永远不可能被entry占用。这样会增加了碰撞的几率,减慢了查询的效率,造成空间的浪费。 length-1 二进制中为1的位数越多,那么分布就平均。
2的倍数是为了 & 的时候叫数据在数组上均匀分布
2 、hashmap的几种构造 ?构造数组的长度和长度+因子的区别?
hashmap 容量初始化 还是默认了初始因子
3、 hashmap 数组的最大长度,hashmap是不是无限大?
最大长度为1<<30
4、hashmap 构造初始化容量13因子0.8,那数组的长度就是 13 吗?
答案不是
源码中的数组初始化长度做了校正,还是2的倍数 最小默认为16
5 、hashmap 为解决hash 冲突使用链表 为啥都是每次放到链表的表头?
java 最近使用原则 索引新的数据放在了表头
6 、链表的上的hash都是一样吗? hash 不同的两个值会在一个链表上吗?
会不会在一个链表上 是通过 hash值和数组的长度-1 & 运算,或造成 key的hash不同,但是落在数组角标相同的位置
最容易出现的情况就是 hash构造的时候参数(12,1.5) 因为容量因子的扩大,会造成更多的不同的hash 落在同一个角标位置。所以就有了链表上多个entry 进行判断的时候
if (p.hash == hash &&
((k = p.key) == key || (key != null && key.equals(k))))
e = p;
7、链表的作用?
hash不同key 也可能在一个链表上,根据判断后相同key直接覆盖,不同的key只能新建一个node
if (p.hash == hash &&
((k = p.key) == key || (key != null && key.equals(k))))
e = p;
这样子快
Map<String, Object> map = new HashMap<>();
map.put("1", 1);
map.put("2", 2);
for (Map.Entry<String, Object> entry : map.entrySet()) {
System.out.println(entry);
System.out.println(entry.getKey());
System.out.println(entry.getValue());
}