hashcode的作用是让基于散列的集合正常的运行,这些散列的集合有:HashSet、HashMap以及HashTable。
举个例子:当我们需要添加一个元素的时候a进Set的时候,我们会计算出a的hashcode,然后求余,得到这个哈希值应该在哪个桶里,最后在桶里边找有没有散列值跟a这个元素的散列值相同的,没有的话,最直接添加;有的话,再用equals方法判断,添加的值。
有趣的例子1:可变数据类型的操作改变,导致哈希值的改变
List<String> list = new ArrayList<>();
list.add("a");
Set<List<String>> set = new HashSet<>();
set.add(list);//把list添加到set里
System.out.println(set.contains(list));//true
list.add("b");//对list进行操作
list.add("c");
System.out.println(set.contains(list));//false,为什么不是true
简述:
??
有趣的例子2 重写equals方法要重写hashcode
比较有两种方式行为比较和观察比较,为了满足我们需要的比较,我们改写equals方法,下面是代码
public static void main(String args[]){
Set<Student> s = new HashSet<>();
s.add(new Student("a","b"));
System.out.println("添加完毕");
System.out.println(s.contains(new Student("a","b")));
}
public class Student{
public final String start;
public final String stop;
public Student(String start,String stop) {
this.start = start;
this.stop = stop;
}
@Override
public boolean equals(Object s) {
if(!(s instanceof Student)) {
return false;
}
Student ss = (Student) s;
System.out.println("equals方法被调用啦");
return start.equals(ss.start) && stop.equals(ss.stop);
}
}
但是结果却是false,这是因为前边说过,判断是否包含,需要判断hashcode是否相等,再使用equals,这里我们虽然重写了equals方法,但是由于是两个new,他们的地址肯定不同(即hashcode不相同),运行可以得到验证
所以还要再重写hashcode,在Student里边添加下面代码
@Override
public int hashCode() {
int result = 17;
result = 31*result + start.hashCode();
result = 31*result + stop.hashCode();
System.out.println("hashcode方法被调用啦"+" "+"hashcode: "+result);
return result;
}
这里还有一个很有意思的验证,验证了set使用contains判断是否包含的步骤是怎么样的,再次运行,打印出来的结果是:
hashcode方法被调用啦 hashcode: 19442
添加完毕
hashcode方法被调用啦 hashcode: 19442
equals方法被调用啦
true
说明每次new都回去查看这个new的散列值,当处理contains的时候,就拿第二个new的值,去跟set所有的散列值比,如果相同的话,就继续调用equals