HashMap容量设置 冷不防 2022-05-18 05:15 198阅读 0赞 1、当我们往hashmap中put元素的时候,先根据key的hash值得到这个元素在 数组中的位置(即下标),然后就可以把这个元素放到对应的位置中了。 如果这个元素所在的位置上已经存放有其他元素了,那么在同一个位子上的元素将以链表的 形式存放,新加入的放在链头,比如a->b->c,新加入的d放到a的位置前面,最先加入的放在链尾, 也就是c。最后变成d->a->b->c,从hashmap中get元素时,首先计算key的hashcode,找到数组中对应位置的某一元素, 然后通过key的equals方法在对应位置的链表中找到需要的元素。 2、 在hashmap中要找到某个元素,需要根据key的hash值来求得对应数组中的位置。如何计算这个位置就是hash算法。前面说过hashmap的数据结构是数组和链表的结合, 所以我们当然希望这个hashmap里面的元素位置尽量的分布均匀些,尽量使得每个位置上的元素数量只有一个,那么当我们用hash算法求得这个位置 的时候, 马上就可以知道对应位置的元素就是我们要的,而不用再去遍历链表。所以我们首先想到的就是把hashcode对数组长度取模运算,这样一来,元素的分布相对来说是比较均匀的。 但是,“模”运算的消耗还是比较大的,能不能找一种更快速,消耗更小的方式那?java中时这样做的, Java代码 staticintindexFor(inth,intlength)\{ returnh&(length-1); \} 首先算得key得hashcode值,然后跟数组的长度-1做一次“与”运算(&)。看上去很简单,其实比较有玄机。比如数组的长度是2的4次方, 那么hashcode就会和2的4次方-1做“与”运算。 很多人都有这个疑问,为什么hashmap的数组初始化大小都是2的次方大小时,hashmap 的效率最高,我以2的4次方举例,来解释一下为什么数组大小为2的幂时hashmap访问的性能最高。 看下图,左边两组是数组长度为16(2的4次方),右边两组是数组长度为15。 两组的hashcode均为8和9,但是很明显,当它们和1110“与”的 时候,产生了相同的结果,也就是说它们会定位到数组中的同一个位置上去,这就产生了碰撞,8和9会被放到同一个链表上, 那么查询的时候就需要遍历这个链 表,得到8或者9,这样就降低了查询的效率。同时,我们也可以发现,当数组长度为15的时候,hashcode的值会与14(1110)进行“与”,那么 最后一位永远是0, 而0001,0011,0101,1001,1011,0111,1101这几个位置永远都不能存放元素了,空间浪费相当大,更糟的是 这种情况中,数组可以使用的位置比数组长度小了很多, 这意味着进一步增加了碰撞的几率,减慢了查询的效率!所以说,当数组长度为2的n次幂的时候,不同的key算得得index相同的几率较小,那么数据在数组上分布就比较均匀,也就是说碰撞的几率小, 相对的,查询的时候就不用遍历某个位置上的链表,这样查询效率也就较高了。说到这里,我们再回头看一下hashmap中默认的数组大小是多少,查看源代码可以得知是16,为什么是16,而不是15, 也不是20呢,看到上面 annegu的解释之后我们就清楚了吧,显然是因为16是2的整数次幂的原因,在小数据量的情况下16比15和20更能减少key之间的碰撞,而加快查询 的效率。 3、 当hashmap中的元素越来越多的时候,碰撞的几率也就越来越高(因为数组的长度是固定的),所以为了提高查询的效率,就要对hashmap的数组进行 扩容,数组扩容这个操作也会出现在ArrayList中,所以这是一个通用的操作,很多人对它的性能表示过怀疑,不过想想我们的“均摊”原理,就释然了, 而在hashmap数组扩容之后,最消耗性能的点就出现了:原数组中的数据必须重新计算其在新数组中的位置,并放进去,这就是resize。 那么hashmap什么时候进行扩容呢?当hashmap中的元素个数超过数组大小\*loadFactor时,就会进行数组扩容,loadFactor的 默认值为0.75,也就是说,默认情况下,数组大小为16,那么当hashmap中元素个数超过16\*0.75=12的时候,就把数组的大小扩展为 2\*16=32,即扩大一倍,然后重新计算每个元素在数组中的位置,而这是一个非常消耗性能的操作,所以如果我们已经预知hashmap中元素的个数,那 么预设元素的个数能够有效的提高hashmap的性能。 比如说,我们有1000个元素new HashMap(1000), 但是理论上来讲new HashMap(1024)更合适,不过上面annegu已经说过,即使是1000,hashmap也自动会将其设置为1024。 但是new HashMap(1024)还不是更合适的,因为0.75\*1000 < 1000, 也就是说为了让0.75 \* size > 1000, 我们必须这样new HashMap(2048)才最合适,既考虑了&的问题,也避免了resize的问题。
相关 HashMap初始化容量设置 从JDK8开始,HashMap采用数组+链表+红黑树的方式存储数据。HashMap的CAPACITY默认值是16,参考源码:static final int DEFAUL... 墨蓝/ 2024年05月09日 09:05/ 0 赞/ 34 阅读
相关 HashMap使用时指定容量 目录 文章目录 一、为什么要指定容量 二、使用方式 1.确定阈值 2.示例 总结 -------------------- 一、为什么要指定容量 ![ 以你之姓@/ 2023年09月27日 13:00/ 0 赞/ 59 阅读
相关 Java集合HashMap初始容量与容量大小 Java集合HashMap初始容量与容量大小 这是两个问题 为什么设置初始容量 初始容量多大合适 第一个问题:为什么设置初始容量 这个答案其实通过阅读 曾经终败给现在/ 2022年12月23日 06:15/ 0 赞/ 129 阅读
相关 阿里《JAVA开发手册》为什么建议设置HashMap的初始容量,设置多少合适 目录 要设置HashMap的初始化容量 HashMap初始化容量设置多少合适 -------------------- ![watermark_type_ZmFuZ3p 男娘i/ 2022年09月07日 10:00/ 0 赞/ 158 阅读
相关 HashMap的容量与扩容 HashMap的容量与扩容 //默认的桶数组大小 static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; 末蓝、/ 2022年07月25日 16:55/ 0 赞/ 192 阅读
相关 HashMap容量设置 1、当我们往hashmap中put元素的时候,先根据key的hash值得到这个元素在 数组中的位置(即下标),然后就可以把这个元素放到对应的位置中了。 如果这个元素所在的位 冷不防/ 2022年05月18日 05:15/ 0 赞/ 199 阅读
相关 HashMap容量解析 HashMap中有一个有参的构造方法,传递的参数是map初始化的容量。那么给定的参数,HashMap就一定给分配参数对应的容量吗?比如,我传7进去,HashMap就会给分配7个 短命女/ 2022年04月16日 01:55/ 0 赞/ 242 阅读
相关 HashMap的容量与扩容 [https://blog.csdn.net/gaopu12345/article/details/50831631][https_blog.csdn.net_gaopu123 超、凢脫俗/ 2022年03月06日 01:40/ 0 赞/ 230 阅读
相关 为什么要设置HashMap的初始化容量 经常在初始化hashmap的时候出现如下情况 ![在这里插入图片描述][20190807171404985.png] 《阿里巴巴Java开发手册》解释 ![在这里插 - 日理万妓/ 2021年11月04日 19:20/ 0 赞/ 305 阅读
还没有评论,来说两句吧...