查找效率高、避免DoS攻击链表比较短的时候 不需要树化,红黑树占用内存多一些在负载因子0.75的情况下,长度超过8的链表出现概率极低(0.00000006),所以选择8是为了让树化几率足够小当一个链表长度大于8的时候,会先扩容(所以链表长度是有可能超过8的),来解决链表过长问题
如果集合长度超过64,依然存在链表长度大于8,才会转变为红黑树。
- 集合扩容时可能会拆分红黑树,当树元素<=6就会退化链表remove树节点时,若root、root.left、root.right、root.left.left有一个为Null,也会退化为链表
索引如何计算?hashCode存在,为什么还要提供hash()方法?数组容量为何是2的n次幂?
对 对象进行hashCode 获取原始hash,再使用hashMap的hash方法进行二次hash,最后使用二次hash结果和数组容量进行取模。为了综合高位数据,让哈希分布更均匀设计者综合各种因素 如(可以用&运算 替换取模运算 增加效率)数组长度为质数的时候,hash分布更加均匀,但是效率不如2的n次幂。
put方法流程?
- 首次调用Put方法时候创建数组计算索引(桶下表)如果桶下表没有被占用,创建Node占位返回如果被占用了,
是TreeNode走红黑树的添加或更新逻辑是普通Node,走链表的更新或添加逻辑,如果链表长度超过树化阈值,走树化逻辑
返回前检查容量是否超过阈值,一旦超过则扩容
补充: jdk8中如果元素索引相同,每次新添加的元素,会放到链表的最后
加载因子为什么默认是0.75f?
在空间占用与查询时间之间取得较好的权衡大于这个值,空间节省了,但链表就会比较长影响性能小于这个值,冲突减少,但扩容就会更频繁,空间占用多
多线程下 数据错乱
多个线程同时操作hashmap 就有可能出现数据丢失
key是否能够为Null?作为key的对象有什么要求?
hashMap的key可以为null,其他Map不一定能为null
- 作为key对象,必须实现hashCode和equals,并且key的内容不可修改(不可变)
String对象的hashCode()如何设计,为什么每次都乘31?
为了达到较为均匀的散列效果,每个字符串的hashCode足够独特31代入公式有较好的散列特性,并且31 * h可以优化为 h << 5 - h



