hashMap和HashSet的put()操作
1.1、底层
hashMap和Map底层是哈希表结构,HashSet也是用到了HashMap的put()操作
哈希表是数组+链表+红黑树组成
1.2、前提了解
1.2.1、
成员变量,这个是节点数组,存储链表的数组,默认初始长度为16
1.2.2
resize()方法是调整节点数组长度大小的方法,默认数组长度是16,加载因子为0.75,单存储到16*0.75 = 12个元素的时候会进行扩容,扩容到原来的2倍长度为32个数组长度
1.2.3
hash()方法是获取到hash值的方法,用到的是hashCode()这个方法,如果不重写,调用的就是Object类中的hashCode()方法,获取的就是根据地址值生成的hash值
1.2.4
节点Node类
1、hash为存储元素key的哈希值
2、key key值
3、value value值
4、next 下一个节点
1.3、put()源码查看
1.3.1
调用put()方法将调用putVal()方法,将hash值,key,value,false,true这5个参数传递进去
1.3.2
1、创建节点数组和节点
2、将当前节点数组table赋值给tab,tab等于空或者tab的长度为0都将会执行最后一句语句
3、如果条件判断成功,可以证明节点数组还没有给出默认大小,调用resize()调整数组长度大小(默认初始长度大小为16),在赋值给tab,将tab节点数组的长度大小赋值给n
1.3.3
1.3.4
else上面就是节点数组中找到了位置,该位置中还没有元素,那么就将元素存储进去
else下面就是找到了位置,并且位置上有元素,那么我们就要进行一系列的判断了,下面我们就具体分析else里面的内容
1.3.4.1、第一个判断内容分析
分析一:
分析二:
1、既然用到了红黑树,那么我们就要想tree中我们自己定义的规则,比较器排序和自然排序定义定义规则,那么Map中的红黑树是怎么定义规则的?
2、图中我们可以看到红黑树存储将hash值传递过去了,那么红黑树存储就是用hash值来进行存储
3、可以看到p强制转换为红黑树的类型
分析三:
1.3.4.2、第二个判断内容分析
返回的旧值,是给hashMap使用
1.3.5
if里面判断需不需要给数组扩容
返回的null是给hashSet来使用,接下来我们看hashSet里面的add方法,返回为null就代表添加成功
1.4总结
1、我们要使用hash就必须要重写hashCode()和equals方法
2、hashCode()方法是依据属性值来进行计算,equals是比较属性值是否一样
3、两个属性值相同的对象hash值也是一样的,他们会找到在节点数组中相同的位置存储,在调用equals方法进行属性比较,相同不会存储
4、不同属性值的对象可能会找到在节点数组中相同的位置存储