说在前面

​ 在HashMap中,默认创建的数组长度是16,也就是哈希桶个数为16,当添加key-value的时候,会先计算出他们的哈希值(h = hash),然后用return h & (length-1)就可以算出一个数组下标,这个数组下标就是键值对应该存放的位置。

​ 但是,当数据较多的时候,不同键值对算出来的hash值相同,而导致最终存放的位置相同,这就是hash冲突,当出现hash冲突的时候,该位置的数据会转变成链表的形式存储,但是我们知道,数组的存储空间是连续的,所以可以直接使用下标索引来查取,修改,删除数据等操作,而且效率很高。而链表的存储空间不是连续的,所以不能使用下标 索引,对每一个数据的操作都要进行从头到尾的遍历,这样会使效率变得很低,特别是当链表长度较大的时候。为了防止链表长度较大,需要对数组进行动态扩容。

​ 数组扩容需要申请新的内存空间,然后把之前的数据进行迁移,扩容频繁,需要耗费较多时间,效率降低,如果在使用完一半的时候扩容,空间利用率就很低,如果等快满了再进行扩容,hash冲突的概率增大!!那么什么时候开始扩容呢???

​ 为了平衡空间利用率和hash冲突(效率),设置了一个加载因子(loadFactor),并且设置一个扩容临界值(threshold = DEFAULT_INITIAL_CAPACITY * loadFactor),就是说当使用了16*0.75=12个数组以后,就会进行扩容,且变为原来的两倍。

  • 为什么加载因子是0.75呢?

    先看一段源码注释:

    Because TreeNodes are about twice the size of regular nodes, we
    * use them only when bins contain enough nodes to warrant use
    * (see TREEIFY_THRESHOLD). And when they become too small (due to
    * removal or resizing) they are converted back to plain bins. In
    * usages with well-distributed user hashCodes, tree bins are
    * rarely used. Ideally, under random hashCodes, the frequency of
    * nodes in bins follows a Poisson distribution
    * (http://en.wikipedia.org/wiki/Poisson_distribution) with a
    * parameter of about 0.5 on average for the default resizing
    * threshold of 0.75, although with a large variance because of
    * resizing granularity. Ignoring variance, the expected
    * occurrences of list size k are (exp(-0.5) * pow(0.5, k) /
    * factorial(k)). The first values are:
    *
    * 0: 0.60653066
    * 1: 0.30326533
    * 2: 0.07581633
    * 3: 0.01263606
    * 4: 0.00157952
    * 5: 0.00015795
    * 6: 0.00001316
    * 7: 0.00000094
    * 8: 0.00000006
    * more: less than 1 in ten million

    大概意思就是说,在理想情况下,使用随机哈希码,节点出现的频率在hash桶中遵循泊松分布,同时给出了桶中元素个数和概率的对照表。从上面的表中可以看到当桶中元素到达8个的时候,概率已经变得非常小,也就是说用0.75作为加载因子,每个碰撞位置的链表长度超过8个的概率达到了一百万分之一。

为什么HashMap的加载因子是0.75?的更多相关文章

  1. HashMap默认加载因子为什么选择0.75?(阿里)

    Hashtable 初始容量是11 ,扩容 方式为2N+1; HashMap 初始容量是16,扩容方式为2N; 阿里的人突然问我为啥扩容因子是0.75,回来总结了一下: 提高空间利用率和 减少查询成本 ...

  2. [转]为什么Java中的HashMap默认加载因子是0.75

    前几天在一个群里看到有人讨论hashmap中的加载因子为什么是默认0.75. HashMap源码中的加载因子 static final float DEFAULT_LOAD_FACTOR = 0.75 ...

  3. 关于new HashMap<>(1)中1的理解(hashMap的加载因子)

    新入公司,阅读代码的时候发现了一行代码,为 Map<String, String> map=new HashMap<>(1); 对于这个括号里面的1不能理解,于是查了资料,大概 ...

  4. HashMap 扩容 加载因子

    HashMap: public HashMap(int initialCapacity, float loadFactor) { //初始容量不能<0 if (initialCapacity & ...

  5. 为什么HashMap初始大小为16,为什么加载因子大小为0.75,这两个值的选取有什么特点?

    先看HashMap的定义: public class HashMap<K,V>extends AbstractMap<K,V>implements Map<K,V> ...

  6. ArrayList、Vector、HashMap、HashSet的默认初始容量、加载因子、扩容增量

    当底层实现涉及到扩容时,容器或重新分配一段更大的连续内存(如果是离散分配则不需要重新分配,离散分配都是插入新元素时动态分配内存),要将容器原来的数据全部复制到新的内存上,这无疑使效率大大降低. 加载因 ...

  7. ArrayList、Vector、HashMap、HashTable、HashSet的默认初始容量、加载因子、扩容增量

    这里要讨论这些常用的默认初始容量和扩容的原因是: 当底层实现涉及到扩容时,容器或重新分配一段更大的连续内存(如果是离散分配则不需要重新分配,离散分配都是插入新元素时动态分配内存),要将容器原来的数据全 ...

  8. List、Map、set的加载因子,默认初始容量和扩容增量

    首先,这三个概念说下.初始大小,就是创建时可容纳的默认元素个数:加载因子,表示某个阀值,用0~1之间的小数来表示,当已有元素占比达到这个阀值后,底层将进行扩容操作:扩容方式,即指定每次扩容后的大小的规 ...

  9. Java集合类初始容量、加载因子、扩容增量

    当底层实现涉及到扩容时,容器或重新分配一段更大的连续内存(如果是离散分配则不需要重新分配,离散分配都是插入新元素时动态分配内存),要将容器原来的数据全部复制到新的内存上,这无疑使效率大大降低. 加载因 ...

随机推荐

  1. lqb 基础练习 特殊回文数

    基础练习 特殊回文数 时间限制:1.0s   内存限制:512.0MB     问题描述 123321是一个非常特殊的数,它从左边读和从右边读是一样的. 输入一个正整数n, 编程求所有这样的五位和六位 ...

  2. 从壹开始 [ Design Pattern ] 之一 ║ 设计模式开篇讲

    缘起 不说其他的没用的开场白了,直接给大家分享三个小故事,都来自于我的读者粉丝(我厚着脸皮称为粉丝吧

  3. 【2018寒假集训 Day2】【动态规划】钱币兑换(exchange)(自己翻译的2333)

    钱币兑换(exchange) 问题描述: Dave偶然获得了未来几天的美元(dollars)与马克(marks)之间的兑换率.例如Dave开始有100marks,请编写个程序帮助Dave找出最好的买卖 ...

  4. 自学python day 10 函数的动态参数、命名空间、作用域

    作业提升: s为字符串 s.isalnum() 所有字符都是字母或者数字 s.isalpha() 所有字符都是字母 s.isdigit() 所有字符否是数字 2. for i in range(1,1 ...

  5. Scrapy中的反反爬、logging设置、Request参数及POST请求

    常用的反反爬策略 通常防止爬虫被反主要有以下几策略: 动态设置User-Agent(随机切换User-Agent,模拟不同用户的浏览器信息.) 禁用cookies(也就是不启用cookies midd ...

  6. Kibana笔记

    • 根据id查询 GET index_1/doc/1 • 全文检索 GET index_1/doc/_search GET index_1/doc/_search{ "query" ...

  7. MyEclispe启动Tomcat7时出现错误The servlets named [LoginServlet] and [com.liu.control.LoginServlet] are both

    刚开始尝试写Servlet代码,第一天就碰到这个错误,在网上找了很多资料才找到解决办法,在此记录一下. org.apache.catalina.LifecycleException: Failed t ...

  8. jquery列表操作

    <span> <button>全选</button> <button>不选</button> <button>反选</bu ...

  9. 如何将本地项目推送到码云仓库或者GitHub仓库

    将本地项目推送到码云仓库. 前提: git 和码云   1.在码云上先创建一个仓库. 2.在要被上传的项目的目录右键, 选择 Git Bash Here. 3.在窗口输入命令: git init 这时 ...

  10. TypeScript躬行记(1)——数据类型

    TypeScript不仅支持JavaScript所包含的数据类型,还额外扩展了许多实用的数据类型,例如枚举.空值.任意值等. 一.JavaScript的数据类型 JavaScript的数据类型包括6种 ...