HashMap底层实现是一个键值对Node数组,而Node实现了键值对Map.Entry接口
![]()
HashMap类继承结构图


1. HashMap对象的创建
1.1 默认的构造方法——只指定自动扩容时的加载因子loadFactor

1.2 对初始容量或加载因子设定的构造方法



通过tableSizeFor源码分析,我们知道如果传入参数是2的次方,比如1,2,4,8...,那么最终的返回值就是本身;如果不是,那么返回的是大于参数值,且最接近参数值的2的次方。如9,返回的是16,15返回的也是16。所以我们总结tableSizeFor方法的作用就是得到大于原始值的最小的2的次方。
1.3 传入Map对象的构造方法

总结:HashMap的构造方法主要就是对threshold和loadFactor属性赋值;但是我们发现只有默认构造方法没有对threshold属性赋值,而且类中有个常量属性DEFAULT_INITIAL_CAPACITY,这里先记住,后面会有用。

2. HashMap添加元素
2.1 Map添加元素使用的是put方法,参数是key和value。内部调用putVal方法,参数是key的hash值,key,value,false,以及true,记住这些参数,后面分析putVal方法需要使用。

2.2 putVal源码分析



2.3 总结:不考虑特殊情况以及数值超界,添加元素的逻辑为:根据key的hashcode简单变形得到hash值,然后将该hash值映射到哈希表的索引。判断该索引是否为null,为null,则使用信息创建新节点;不为null则判断该索引的第一个节点是否和当前要添加节点的hash值以及==或equals相等,相等更新该节点的值即可。如果没找到则判断当前索引是否已经转为红黑树(转为树的条件是哈希表数组大小大于等于64,并且单链表节点数大于等于8),如果是红黑树,则使用红黑树的节点添加方法;如果不是,则一直比对当前节点链表,找到更新值,找不到添加至尾部。所以我们需要重写hashcode方法和equals方法,不然自带的hashcode比较的是内存地址。
3. HashMap通过key获取元素


4. HashMap其它常用方法
4.1 keySet和values方法得到key集合和value集合,keySet和values是内部属性。


4.2 remove方法移除某元素——先寻找再移除


4.3 clear方法清空

4.4 containsKey方法判断是否包含key


4.5 containsValue方法判断哈希表是否包含某个value,很费时间,少用。

5. HashSet。
5.1 HashSet构造方法内部实际使用HashMap对象。
![]()

5.2 数据存储时,只记录key,不记录value而已,value使用内部的一个Object类型常量PRESENT。


本文详细探讨了HashMap的底层实现,包括它作为一个键值对Node数组的结构,自动扩容机制,以及为何需要重写hashcode和equals方法。在HashMap的创建过程中,构造方法会设置初始容量和加载因子。添加元素时,通过put方法计算key的hash值并映射到哈希表索引,处理冲突时可能涉及红黑树转换。同时,文章指出重写hashcode和equals方法对于正确操作HashMap的重要性。



1290

被折叠的 条评论
为什么被折叠?



