hashMap结构图
1.简介
hashMap底层数据结构主要包括三个部分:数组、链表、以及红黑树三部分组成实现
1.数组
hashMap内部有一个Entry数组,用于存储键值对,Entry是hashMap内部的一个类,有两个属性k和v代码key和value,数组的每个元素被称为“桶”、“节点”等等
数组的官方定义:数组是一种数据结构,用于存储相同类型的元素集合。它由一组按顺序排列的元素组成,每个元素可以通过索引来访问
2.链表
Node(int hash, K key, V value, Node<K,V> next) {
this.hash = hash;
this.key = key;
this.value = value;
this.next = next;
}
//单项链表 第三个参数表示下一个节点 没有上一个
这里的Entry对象的hash值如果相同,则会被存储在一个桶中形成一个链表
3.红黑树
当同一个桶中的Entry对象数量达到一定数量(默认为8),hashMap会将这个桶中的Entry转换成红黑树,当链表中的Entry数量较少时,重新转换为链表,这样设计可以提高查找效率
2.HashMap重要方法
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
//这里可以先去了解一下位运算
/*Java的HashMap中,没有直接使用hashcode() 作为HashMap中的hash值
HashMap中将hashcode() 的值无符号右移16位得到一个新值,然后将hashcode() 的值和这个新值进行异或运算得到最终的hash值保存在HashMap中. 这样可以避免哈希碰撞
比如容量大小n为16时 ,n-1为15(0x1111), 散列值真正生效的只是低4位,此时新增的键的hashcode() 的值如果是2,18,34这样以16的倍数为差的等差数列时,就会产生大量的哈希碰撞
使用这样的方法,将高16位和低16位进行异或,因为大部分hashcode() 的值分布已经很均匀了,即使发生碰撞也用O(logn)O(logn)O(logn)时间复杂度的红黑树进行了优化.这样通过使用异或的方法,不仅减少了系统开销,也不会因为tab长度较小时高位没有参与下标的运算引发哈希碰撞 */
3.HashMap存储键值对的过程
4.HashMap常见问题
1.HashMap的key可以为null吗?|key为null存储在什么位置
可以存储 null 的 key 和 value,但 null 作为键只能有一个,null 作为值可以有多个 |key为null 存在tab[0]的位置