hashmap

jdk7 hashmap


hashmap的 成员变量有节点数组,加载因子,当前hashmap数据个数,扩展阀值(当元素个数达到这个阀值时就扩充)。默认加载因子是0.75,默认初始化大小是16,默认最大数量是2的30次方,因为int是4字节,32位,最高位是符号位,所以最多可以左移30位,而不能移动到处在最高位的符号位!。
是由数组和链表实现的,根据key算出hashcode,根据hashcode和数组长度求余数得到数组下标,数组下标相同的构成同一个链表。下标相同的元素插入链表时采用的是头插法。
hashmap的容量一定是2的幂,查找最小的且大于等于给定初始容量的时候是根据位移和或运算来实现的。因为2的幂的二进制中只有一位是1,其余都是0.如:4是 0100,2是0010,8是0000 1000 。所以通过位移把给定数值最高位后面的值全部设置为1,然后用得到的值减去(得到的值右移一位的值)就是最大的且小于给定值的2的幂。比如给定的是6,6的二进制是0110,先通过位移得到0111,使用0111 减去0011(是通过0111右移一位得到的)得到0100,即是4.
最后再把得到的值左移一位就得到了最小的且大于等于给定容量的2的幂。4 左移一位是8.
数组的容量为什么是一定要是2的幂?
    (1)根据key计算数组下标的时候根据位移计算更快
    添加数据时,根据key的哈希值得到的数组的下标索引范围是0-->数组长度-1.
    (2)方便扩容
hashmap的哈希值不是直接计算的key的哈希值,二是经过了异或以及位移以及求幂等一系列操作得到的值。 key为null的时候,放在数组下标为0的链表中。如果哈希值不重新计算,下标有个规律,一种情况是不变,另一种情况是原来的下标加上扩容的值。比如,容量是16,原来下标是6,扩容到32后,哈希不重新计算的情况下,下标要么是6要么是22.
扩容时会遍历所有的数据,重新计算下标,重新存储。node节点的Entity不会重新生成,只是转移。
扩容后,单个链表中的顺序颠倒了下(即原来的头变成了尾,尾变成了头,如果所有元素都还在同一个链表的情况下,也有可能部分元素已迁移到了另一个链表)
jdk7hashmap扩容可能出现死循环。原因是扩容时链表移动时链表元素顺序颠倒了。
可以在环境变量中设置参数值jdk.map.althashing.threshold的大小,当容量大于等于该值的时候,重新计算哈希,重新散列存储。
如何防止扩容,再已知要存储数量打下的话,就可以设置初始容量和阀值大于存储数量就可以防止扩容。
modCount是用来快速失败的,是一种容错机制。当hashmap返回的迭代器迭代的过程中使用了hashmap的remove方法删除了元素,再继续迭代时会报错,使用迭代器的删除方法就可以避免。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值