1.HashSet对象的创建
创建HashSet对象:
package com.jd.add;
import java.util.HashSet;
public class Test1 {
public static void main(String[] args) {
HashSet<String> set = new HashSet<String>();
set.add("Jim");
}
}
按住Ctrl进入HashSet构造方法的底层代码,我们可以看到,其实质时创建了一个HashMap类集合的对象,并将地址赋值给了全局变量map。
public HashSet() {
map = new HashMap<>();
}
2.分析add方法
鼠标放在add上,按住Ctrl键进入底层代码:
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
由上面代码,我们可以知道,add方法的返回值是用map调用HashMap的put方法,接着进入put方法底层:
public V put(K key, V value) {
return putVal(hash(key), key, value, false, true);
}
进入put后继续调用putVal方法,此方法的第一个参数传入的是一个参数为key的hash方法返回值,进入hash方法:
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
该方法的返回值是由一个三目运算符通过运算得出的,传入参数key(最初传入HashMap集合的对象),等于null时,返回值为0;不等于null时,返回一个由位运算符计算得出的数据,在这个表达式中,key调用了hashCode方法,分析hashCode方法:
public native int hashCode();
进入hashCode方法后发现其被native修饰且没有方法体,说明此方法是由底层的c语言实现的,所以我们写段代码来测试一下hashCode方法的作用是什么
测试代码:
public class Test1 {
public static void main(String[] args) {
Test test=new Test1();
System.out.println(test);
System.out.println(test.hashCode());
}
}
输出:
hashset.Test1@52e922
5433634
在测试代码中,test属于引用型数据,其存储的是堆中对象的地址,所以直接输出test的结果是一串地址;当test调用hashCode方法并输出时,输出一串数字,我们调用方法将数字转换为十六进制,发现输出结果就是就是test存储的地址值
public class Test {
public static void main(String[] args) {
Test test=new Test();
System.out.println(test);
System.out.println(test.hashCode());
System.out.println(Integer.toHexString(test.hashCode()));
}
}
输出:
hashset.Test1@52e922
5433634
52e922
由此可得:hashCode方法的作用是打印对象的地址
但是要注意,如果调用hashCode方法的对象是String类型,若两个对象的地址值不同,但字符串的内容相同,此时hashCode方法的返回值相同。
public class Test {
public static void main(String[] args) {<