定义
首先我们要知道什么是HashMap,HashMap是基于哈希表的数据结构,可以说是基于数组+链表+红黑树(java8之前是数组+链表)实现的map类
哈希表是什么?
哈希表(Hash table,也叫散列表),是根据关键码值(Key value)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。
在java8之前的结构
数组
HashMap的核心实质上是一个entry数组,这个数组的大小总是2的幂
链表
当遇到哈希冲突即多个键经过哈希运算后映射的数组的同一个索引上时,就会形成链表
java8及之后的结构
数组
仍然是一个entry数组,java8及之后称为Node,大小仍然是2的幂
思考:为什么要是2的幂呢?
首先看源码我们知道HashMap中数组的初始长度默认为16
最大容量:如果任一带有参数的构造函数隐式指定了更高的值,则使用最大容量。必须是2的幂且 <= 1 << 30
如果我们传入的初始容量不是2的幂,他就会将这个数改成大于该数且最接近该数的2的幂,比如我初始容量为13,他就会改成大于13且最接近13的2的幂也就是2^4=16,下面我们来看看源码是怎么做的
当我们使用构造方法传进来一个初始容量的值initialCapacity,默认会传入一个加载因子0.75(DEFAULT_LOAD_FACTOR),通过this关键字调用了本类的另外一个重载方法
继续追踪下去,可以看到
1.首先判断传来的初始容量是否小于0,是则抛出异常
2.再判断是否初始容量值是否超过了最大容量(2^30),如果超过了就等于最大容量
3.再接着判断加载因子是否小于等于0或者不是一个数字,如果小于等于0或者不是数字就抛出异常
4.然后调用了一个tableSizeFor()方法去处理传进来的初始容量
跟踪下去进入到tableSizeFor()
方法,这个方法的作用就是返回一个大于输入参数且最接近2的幂的数
负载因子:默认为0.75,负载因子决定了哈希表在自动扩容之前可以达到多满的程度,当存储的元素数量超过容量*负载因子时就会触发扩容操作,默认容量16和默认负载因子0.75这个组合是在性能和空间之间找到的平衡。较高的负载因子会减少空间浪费,但会增