基础介绍
打开JDK的API我们知道HashMap的语法特性:
1、hashMap存储的是键值对数据;
2、允许null键null值;
3、键是唯一的,值是可重复的;
4、实现非同步的,也就是线程不安全。
知道这些,在日常应用中就可以入门了。
深入研究
如果想更好地运用hashMap,完全掌控它,就必须了解它内部的原理结构;
这样你才可以在面对hashMap的时候更加从容自信!
结构
上图很好的说明了hashMap的内部结构:数组 + 链表; 其横向图块0——6代表数组,纵向图块既是链表;图块表示bucket,俗称桶,是hashMap中的基本单位。
当我们往hashMap中put元素的时候,会对键执行hashcode运算,找到bucket的位置, 然后在bucket中存储键值对。
此时我们明白了,键值对存储在一个bucket中,所以在api中通过entrySet获取的实际上是所有的bucket,bucket在代码中被entry所表示。
hash冲突
我们知道了hashMap根据键进行hashcode找到bucket的位置,如果两个键的hashcode一样会发生什么呢?
会发生冲突,因为两个键找到的是同一个bucket,而一个bucket只能存储一个键值对,在这种情况下hashMap会对键进行equals,来确定两个键内容是否相等:
如果相等,那么就不进行存储,符合hashMap的键唯一原则;
如果不相等,hashMap就会创建一个链表来存储冲突的键值对。
这样我们知道了hashMap是怎么获取hash冲突的键值对:
当从hashMap中get时,首先通过键的hashcode找到bucket所在位置,然后使用equals获取链表中的键值对。
总结
在开发中,一般使用String、Integer这样的wrapper类来作为hashMap的键,因为它们在常量池中,是不可变的,所以hashcode和equals肯定是唯一的,不会发生hash冲突;
因此在bucket中只有一个键值对,不存在链表,从而减少了对链表的增删、遍历的性能消耗,也就提高了hashmap的性能。
总之减少hash冲突的链表,hashMap的性能才能最优。