详述HashSet的add方法实现原理

HashSet概述:HashSet中储存的数据不重复,元素的顺序也是无序的。

添加元素代码

详述HashSet的add方法实现原理

 此时输出set集合中的个数为1,所以可以判断HashSet数据不能重复,调用add方法()为什么不能重复添加 分析如下:

因为我们new HashSet<>();,所有我们需要进入HashSet实现类。

HashSet构造方法源代码

 

详述HashSet的add方法实现原理

 

分析:调用HashSet构造方法时,会创建一个HashMap对象,且赋值给map成员变量  请看源代码(map=new HashMap<>();)

Ctrl+o 搜索add方法   

add源代码

详述HashSet的add方法实现原理

 

分析:通过查看HashSet构造方法源代码,可得知实质上add方法使用的是HashMap中的put方法

HashMap中put方法源代码

详述HashSet的add方法实现原理

 

 

hash方法源代码

详述HashSet的add方法实现原理

 

 

 

分析

分析hash方法,请看方法体三目运算符传入的key值不为空,则执行:后的代码 只要Key对象hashCode相同,则调用改方法的返回值一定相同。所以hash传入相同的对象就会得到相同的结果

put调用putVal方法代码

详述HashSet的add方法实现原理

 

 

分析:添加第一个字符

  1.首先putVal参数列表被传入5个参数,int  hash //是key经过hashCode运算返回的值,key//是put方法传入的值 ,value//是put方法传入的值.onlyIfAbsent//是false,evict//是ture.   Node<K,V>[] tab;//创建了一个局部变量 名为tab的Node数组,table是全局变量数组为null。

  2.第一个if()处:(table为空赋值给tab)==null地址相同成立后面短路,执行改if内容,resize默认长度为16并且赋值给n

  3.第二个if()处:此时n为16(长度)进行&和hash运算赋值给i,i值是第一次存放的位置,因为tab为空所以成立,返回 putVal 返回null,putValf给put方法,add返回ture,添加成功。

   添加第二个字符(和第一个字符相同)

  1.(请看putVal源代码)因为赋值过一次table不为空,不成立执行下一个if(),此时n为16(长度)进行&和hash运算赋值给i,因为两个相同的值进行hashCode运算返回值一定相同,所以位置相同,因为table赋值给tab不为空不成立,tab[i]赋值给p ,p是第一次存的,不成立进入else

  2,p.hash//是第一次存的 hash//当前的  因为内容相同所以地址相同&&Key!=null成立&&key.equals(k)肯定相同, p给e赋值,不管是new 对象还是直接赋值都是true

  equlas在编译时object,运行时是key是什么类型就调用什么类型的equlas方法,key则是上转型对象.

  3执行到if (e != null)e为第一个“jim”,所以不为空执行if语句,把e.value赋值给oldValue

  4,onlyIfAbsent为put方法传进来的参数false,所以执行该if内容。

  5.value(第二个)的赋值给e.value(第一个)被覆盖。返回oldValue。方法结束。

自定义类

自定义student和重写hashCode,equals方法代码

详述HashSet的add方法实现原理

详述HashSet的add方法实现原理

 分析:

  1.因为student为自定义类,没有equals和hashcode方法,会调用object方法下的equals是比较地址,比的不是内容所以需要重写。

  2,重写的hashCode:this是谁调用方法this就是这个对象,放回相同的值

  3.重写的equals()方法:this是谁调用方法this就是这个对象,因为this.id为上转型对象,所以在调用equals()方法时,执行的是该上转型对象对应类中的equals()方法(多态)这时就会调用重写后的equlas方法,两个值进行比较

  4.(请看putVal源代码)因为赋值过一次table不为空,不成立执行下一个if(),此时n为16(长度)进行&和hash运算赋值给i,因为两个相同的值进行hashCode运算返回值一定相同,所以位置相同,因为table赋值给tab不为空不成立,tab[i]赋值给p ,p是第一次存的,不成立进入else

  5,p.hash//是第一次存的 hash//当前的  因为内容相同所以地址相同&&Key!=null成立&&key.equals(k)肯定相同, p给e赋值,不管是new 对象还是直接赋值都是true

  equlas在编译时object,运行时是key是什么类型就调用什么类型的equlas方法,key则是上转型对象.

  6.执行到if (e != null)e为第一个“jim”,所以不为空执行if语句,把e.value赋值给oldValue

  7,onlyIfAbsent为put方法传进来的参数false,所以执行该if内容。

  8.value(第二个)的赋值给e.value(第一个)被覆盖。返回oldValue。方法结束。

 

 

上一篇:java – 导入的appcompat库有错误


下一篇:Angular Material (Components Cdk) 学习笔记 Table