HashSet概述:HashSet中储存的数据不重复,元素的顺序也是无序的。
添加元素代码
此时输出set集合中的个数为1,所以可以判断HashSet数据不能重复,调用add方法()为什么不能重复添加 分析如下:
因为我们new HashSet<>();,所有我们需要进入HashSet实现类。
HashSet构造方法源代码
分析:调用HashSet构造方法时,会创建一个HashMap对象,且赋值给map成员变量 请看源代码(map=new HashMap<>();)
Ctrl+o 搜索add方法
add源代码
分析:通过查看HashSet构造方法源代码,可得知实质上add方法使用的是HashMap中的put方法
HashMap中put方法源代码
hash方法源代码
分析
分析hash方法,请看方法体三目运算符传入的key值不为空,则执行:后的代码 只要Key对象hashCode相同,则调用改方法的返回值一定相同。所以hash传入相同的对象就会得到相同的结果
put调用putVal方法代码
分析:添加第一个字符
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方法代码
分析:
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。方法结束。