前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java HashMap 的那么多为什么

Java HashMap 的那么多为什么

作者头像
syy
发布2020-07-14 15:08:14
2660
发布2020-07-14 15:08:14
举报
文章被收录于专栏:多选参数多选参数
  1. HashMap 的默认大小是 16,这个默认值是可以设置的。如果事先知道具体的例子,可以修改默认初始大小,减少动态扩容的次数,提高性能。修改默认初始大小的值时,比如你设置了 500,那么不会真就使用 500 这个值,而可能会使用 512 这种是 2 的幂的值。 为什么要设置是 2 的幂的值?这个跟下面的 index 的值计算有关,请看第 4 点。
  2. 最大的装载因子为 0.75,当装载因子超过这个值是就会扩容,每次扩容都会扩容为原来的两倍大小。 那么为什么装载因子是 0.75 呢?经研究显示,负载因子是0.75的时候,空间利用率比较高,而且避免了相当多的 Hash 冲突,使得底层的链表或者是红黑树的高度比较低,提升了空间效率(来自网上)。 为啥是扩容为原来的两倍呢?这个具体请看第 4 点。
  3. 采用链表法来解决冲突,之后再 JDK1.8 中引入了红黑数,主要链表长度太长(默认超过8)时,链表就转换为红黑树。当少于 6 时,又将红黑树转换为链表,因为红黑树要维护平衡,比起链表性能上的优势并不会特别明显。 那么为什么在少于 6 的时候而不是 8 的时候才将红黑树转换为链表呢?假设设计成大于 8 时链表转换为红黑树,小于 8 的时候又转换为链表。如果一个 hashmap 不停的插入、删除。hashmap 中的个数不停地在 8 徘徊,那么就会频繁的发生链表和红黑树之间转换,效率非常低。因此,6 和 8 之间来一个过渡值可以减缓这种情况造成的影响。
  4. 散列值的获取分两步走:
代码语言:javascript
复制
// 1. hash 值的计算
static final int hash(Object key) {
 int hash;
 return key == null ? 0 : (hash = key.hashCode()) ^ hash >>> 16;
}

// 2. 插入/查找的时候,计算 key 应该被映射到散列表的什么位置
int index = hash(key) & (capacity - 1)

其中方法 hashcode() 返回的是 Java 对象的 hash_code,这是一个 int 类型的值(32 位)。那么为什么在拿到这个值之后,还需要将自己右移 16 位与自己进行异或呢?因为容量较小的时候,在计算 index 那边,真正用到的其实就只有低几位,假如不融合高低位,那么假设 hashcode() 返回的值都是高位的变动的话,那么很容易造成散列的值都是同一个。但是,假如将高位和低位融合之后,高位的数据变动会最终影响到 index 的变换,所以依然可以保持散列的随机性。 那么在计算 index 的时候,为什么不使用 hash(key) % capacity 呢?这是因为移位运算相比取余运算会更快。那么为什么 hash(key) & (capacity - 1) 也可以呢?这是因为在 B 是 2 的幂情况下:A % B = A & (B - 1)。如果 A 和 B 进行取余,其实相当于把 A 那些不能被 B 整除的部分保留下来。从二进制的方式来看,其实就是把 A 的低位给保留了下来。B-1 相当于一个“低位掩码”,而与的操作结果就是散列值的高位全部置为 0 ,只保留低位,而低位正好是取余之后的值。我们取个例子,A = 24,B =16,那么 A%B=8,从二进制角度来看 A =11000 ,B = 10000。A 中不能被 B 整除的部分其实就是 1000 这个部分。接下去,我们需要将这部分保留下来的话,其实就是使用 01111 这个掩码并跟 A 进行与操作,即可将1000 保留下来,作为 index 的值。而 01111 这个值又等于 B-1。所以 A &(B-1)= A%B。但是这个前提是 B 的容量是 2 的幂,那么如何保证呢?我们可以看到,在设置初始大小的时候,无论你设置了多少,都会被转换为 2 的幂的一个数。之外,扩容的时候也是按照 2 倍进行扩容的。所以 B 的值是 2 的幂是没问题的。

不甘于「本该如此」,「多选参数 」值得关注

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-07-10,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 多选参数 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档