小白 HashMap 源码解析遇到的问题。。

NGU_ALLIN 2018-06-26 11:15:36
在 github上 看到这么一个案例,
HashMap<String, String> map = new HashMap<>();
map.put("K1", "V1");
map.put("K2", "V2");
map.put("K3", "V3");
新建一个 HashMap,默认大小为 16;
插入 <K1,V1> 键值对,先计算 K1 的 hashCode 为 115,使用除留余数法得到所在的桶下标 115%16=3。
插入 <K2,V2> 键值对,先计算 K2 的 hashCode 为 118,使用除留余数法得到所在的桶下标 118%16=6。
插入 <K3,V3> 键值对,先计算 K3 的 hashCode 为 118,使用除留余数法得到所在的桶下标 118%16=6,插在 <K2,V2> 前面。
应该注意到链表的插入是以头插法方式进行的,例如上面的 <K3,V3> 不是插在 <K2,V2> 后面,而是插入在链表头部。


我的理解是 一个桶上面 可以放两个key-value 对或者多个,那整个整个size 是16的话,是不是就不止放16个元素了?这点理解不通了,求高手不吝赐教!
...全文
201 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
NGU_ALLIN 2018-06-27
  • 打赏
  • 举报
回复
引用 5 楼 Ragin 的回复:
我觉得你混淆了HashMap的size和HashMap内部维护的table的size。
每个桶会维护一个链表或者红黑树。
而每个键值对就是链表或红黑树的节点。
这个链表或者红黑树的节点总和才是HashMap的size。

,在初始化的情况下,HashMap的size 是不是就跟它内部维护的table 的size相等呢,
maradona1984 2018-06-27
  • 打赏
  • 举报
回复
引用 3 楼 love_gzd 的回复:
[quote=引用 2 楼 Molly_1994 的回复:]
理论是可以放超过16个元素,但是当元素太多的时候,会经常出现冲突,性能就很差,所以它会进行扩容,然后重新进行计算

嗯,再问下哈,超过16一定会扩容吗,还是说只有冲突比较激烈的时候,才会扩容?[/quote]
扩容的策略你可以通过构造函数的参数确定,默认为当前数组长度*0.75就会扩容,扩容2倍
Braska 2018-06-27
  • 打赏
  • 举报
回复
我觉得你混淆了HashMap的size和HashMap内部维护的table的size。
每个桶会维护一个链表或者红黑树。
而每个键值对就是链表或红黑树的节点。
这个链表或者红黑树的节点总和才是HashMap的size。
stacksoverflow 2018-06-27
  • 打赏
  • 举报
回复
假设capacity是1,那么这个hash表就是一个链表(或者红黑树,暂时不讨论具体数据结构),查找一个元素的复杂度为O(n)级别的,而我们希望的hash表查找一个元素的时间复杂度为O(1)级别的,所以要尽可能不让元素的hashcode重复,这样就要根据loadFactor(负载因子)来计算大概需要多大的数组可以尽可能的满足均匀分布,太大浪费时间,太小回增大查找复杂度。

所以,你说的size16和能存多少个元素没什么关系,只是怎么存的问题。对capacity的调整在HashMap内部有一套规则,楼主有兴趣可以研究一下。
NGU_ALLIN 2018-06-27
  • 打赏
  • 举报
回复
引用 2 楼 Molly_1994 的回复:
理论是可以放超过16个元素,但是当元素太多的时候,会经常出现冲突,性能就很差,所以它会进行扩容,然后重新进行计算

嗯,再问下哈,超过16一定会扩容吗,还是说只有冲突比较激烈的时候,才会扩容?
anakin_feng 2018-06-27
  • 打赏
  • 举报
回复
理论是可以放超过16个元素,但是当元素太多的时候,会经常出现冲突,性能就很差,所以它会进行扩容,然后重新进行计算
Braska 2018-06-27
  • 打赏
  • 举报
回复
引用 9 楼 Ragin 的回复:
[quote=引用 7 楼 love_gzd 的回复:]
,在初始化的情况下,HashMap的size 是不是就跟它内部维护的table 的size相等呢,

table的长度不超过16.实际长度是根据指定的HashMap长度计算。没指定就默认16。
static final int tableSizeFor(int cap) {
int n = cap - 1;
n |= n >>> 1;
n |= n >>> 2;
n |= n >>> 4;
n |= n >>> 8;
n |= n >>> 16;
return (n < 0) ? 1 : (n >= 16) ? 16 : n + 1;
}
[/quote]
我错了, 长度不会超过MAXIMUM_CAPACITY。
Braska 2018-06-27
  • 打赏
  • 举报
回复
引用 7 楼 love_gzd 的回复:
,在初始化的情况下,HashMap的size 是不是就跟它内部维护的table 的size相等呢,

table的长度不超过16.实际长度是根据指定的HashMap长度计算。没指定就默认16。
static final int tableSizeFor(int cap) {
int n = cap - 1;
n |= n >>> 1;
n |= n >>> 2;
n |= n >>> 4;
n |= n >>> 8;
n |= n >>> 16;
return (n < 0) ? 1 : (n >= 16) ? 16 : n + 1;
}
stacksoverflow 2018-06-27
  • 打赏
  • 举报
回复
size就是HashMap中的一个属性,你put一个对象进去size++,你remove一个对象,size--
自己看一下HashMap的代码,不要瞎猜,没有你们想的那么麻烦!
NGU_ALLIN 2018-06-26
  • 打赏
  • 举报
回复
自己顶一下,莫要沉!

62,614

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧