package course; /** * @author WanJl * @version 1.0 * @title Demo05 * @description HashMap * @create 2026/7/31 */ public class Demo05 { /* HashMap集合 HashMap集合是实现了Map接口的一种基于【哈希表结构】实现的集合。 HashMap集合依赖 hashCode方法和equals方法来保证 键Key的唯一。 所以如果自定义类型想要存入到HashMap的Key中,就一定要重写【hashCode方法和equals方法】 哈希值 : 哈希值是JDK根据对象的地址,或者字符串或者数字算出来的int类型的数值。 获取哈希值的方式就是Object类中的hashCode(),返回的就是哈希码值 哈希值的特点: 同一个对象多次调用hashCode()方法,返回的哈希值是相同的。 默认情况下,不同的对象的哈希值是不同的,重写hashCode()可以让我们实现不同对象的哈希值相同。 一般是在多个个对象的所有属性值完全相同时,hashCode()方法需要返回相同的哈希值。 哈希表结构是什么? 哈希表本质来讲,就可以理解为 数组+链表 上面是数组,每个元素都有对应的索引值 其实是一个默认长度为16的数组。 我们往里面添加的键值对的时候,会计算键的哈希值。计算的哈希值其实就是int整数 所以可能出现这样情况: 张三 --hash运算(hashCode) --> 15 李四 --hash运算(hashCode) --> 87 王五 --hash运算(hashCode) --> 66 赵六 --hash运算(hashCode) --> 20 wanjl --hash运算(hashCode) --> 15 哈么么 --hash运算(hashCode) --> 70 HashMap--JDK1.7及之前 数组+链表 的哈希表结构 1、创建一个默认长度为16的,默认的负载因子0.75的数组,数组名table 2、根据元素的哈希值跟数组长度进行计算,计算出应该存入的位置。 3、判断当前的位置是否为null,如果是null就直接存入 4、如果位置不是null,表示有元素,那么就调用equals方法比较这两个元素的属性值,判断是不是同一个。 5、如果判断发现两个对象是同一个,就不存了。如果不是同一个则存入数组,老的元素挂在新元素的下边。 能让两个相同哈希值的对象以链表的方式挂到后面。 原因就只有一个: 虽然哈希值相同,但是equals比较不同。 风险和弊端: 如果出现越来越多的哈希值相同,但是equals比较为false,的元素。 就会导致链表过长,性能下降。 HashMap--JDK1.8之后 JAVA1.8之后,引入了 红黑树,1.8之后的HashMap有两种形态: 第1种:数组+链表--哈希表 第2种:是在哈希表满足了某些条件后,从数组+链表 转换为 数组+红黑树。保证性能不会降低。 简单来说,就是链表的节点数超过8个,就转为红黑树。 HashMap的数组默认长度是16 static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16 默认的负载因子是0.75,当已经存入数组的元素超过长度的0.75,那么就对数组进行扩容 static final float DEFAULT_LOAD_FACTOR = 0.75f; HashMap从数组+链表的结构转为数组+红黑树的结构的阈值,树化阈值是8,链表节点长度超过8就树化。 static final int TREEIFY_THRESHOLD = 8; 当节点长度小于6的时候,会从红黑树退化会链表 static final int UNTREEIFY_THRESHOLD = 6; 数组+链表转为红黑树的第2个条件:数组长度大于64 static final int MIN_TREEIFY_CAPACITY = 64; 总结: 1、HashMap的结构是 数组+链表 2、达到一定条件,会转为 数组+红黑树 3、树化条件:数组长度大于64,链表节点长度超过8。 4、链表节点长度小于6就退化回链表。 */ }