HashMap的数据结构
HashMap是由数组
和链表
构成的,如下图:
用代码来描述如下:
1 | public class HashMap<K,V> { |
变量说明
1 | public class HashMap<K,V> { |
new HashMap()
当我们new一个HashMap时,量化分析法如下。
new HashMap()
- loadFactor = DEFAULT_LOAD_FACTOR; // 0.75f
第1次put
- size++; // 1
- table = new Node[DEFAULT_INITIAL_CAPACITY]; // table.length: 16
- threshold = (int) DEFAULT_INITIAL_CAPACITY * loadFactor; // 12
第2次put
- size++; // 2
- table.length不变; // 16
- threshold不变; // 12
第13次put
- size++; // 13
- table.length扩大一倍;// 32
- threshold扩大一倍;// 24
new HashMap(5)
当我们new一个带一个参数的HashMap时,量化分析法如下。
new HashMap(5)
- loadFactor = DEFAULT_LOAD_FACTOR; // 0.75f
- threshold = 不小于5的最小的2的n次方; // 8
第1次put
- size++; // 1
- table = new Node[threshold]; // table.length: 8
- threshold = (int) table.length * loadFactor;// 6
第2次put
- size++; // 2
- table.length不变; // 8
- threshold不变; // 6
第7次put
- size++; // 7
- table.length扩大一倍; // 16
- threshold扩大一倍; // 12
new HashMap(0/1)
当我们new一个带一个参数的HashMap时,参数值为负数时会报错,参数值为0或1时,量化分析法如下。
new HashMap(0/1)
- loadFactor = DEFAULT_LOAD_FACTOR; // 0.75f
- threshold = 不小于0/1的最小的2的n次方; // 1
第1次put(会扩容)
- size++; // 1
- table = new Node[threshold]; // table.length: 1
- threshold = (int) table.length * loadFactor;// 0
此时由于size > threshold,因此会扩容,扩容后:
- table.length扩大一倍; // 2
- threshold = (int) table.length * loadFactor;// 1
第2次put(会扩容)
- size++; // 2
此时由于size > threshold,因此会扩容,扩容后:
- table.length扩大一倍; // 4
- threshold = (int) table.length * loadFactor;// 2
第3次put(会扩容)
- size++; // 3
此时由于size > threshold,因此会扩容,扩容后:
- table.length扩大一倍; // 8
- threshold = (int) table.length * loadFactor;// 4
第4次put
- size++; // 4
- table.length不变; // 8
- threshold不变;// 4
小结
- 不要new HashMap(0)或者new HasMap(1),即使你只需要存1个值。
- 尽量在new HashMap时指定容量大小,因为默认为16,可能有点浪费。
- 如果你需要存放1~3个,那就new HashMap(2~4)。
- new Hash(2)和new HashMap(3)、new HashMap(4)是一样的。
- 如果想要存放4~6个,那就new HashMap(5~8)。
- 如果想要存放7~12个,那就new HashMap(9~16)或者new HashMap()。
- 并不是new HashMap(初始大小),它的容量就是‘初始大小’。
new HashMap还有两个参数的构造,第二个参数是负载因子,一般不需要指定,默认0.75即可。