为了搞懂这个,小瑶先帮大家复习一下基本概念~然后再举个例子就可以搞懂了,~~~
hashcode epuals ==
== 与 equals的区别
如果两个引用类型变量使用==运算符,那么比较的是地址,它们分别指向的是否是同一地址的对象。结果一定是false,因为两个对象不可能存放在同一地址处。
要求是两个对象都不是能空值,与空值比较返回false。
==不能实现比较对象的值是否相同。
所有对象都有equals方法,默认是Object类的equals,其结果与==一样。
如果希望比较对象的值相同,必须重写equals方法。
hashCode与equals的区别
Object中的equals:
public boolean equals(Object obj) {
return (this == obj);
}
equals 方法要求满足:
自反性 a.equals(a)
对称性 x.equals(y) y.equals(x)
一致性 x.equals(y) 多次调用结果一致
对于任意非空引用x,x.equals(null) 应该返回false
Object中的hashCode:
public native int hashCode();
它是一个本地方法,它的实现与本地机器有关,这里我们暂且认为他返回的是对象存储的物理位置。
当equals方法被重写时,通常有必要重写hashCode方法,以维护hashCode方法的常规约定:值相同的对象必须有相同的hashCode。
object1.equals(object2)为true,hashCode也相同;
hashCode不同时,object1.equals(object2)为false;
hashCode相同时,object1.equals(object2)不一定为true;
当我们向一个Hash结构的集合中添加某个元素,集合会首先调用hashCode方法,这样就可以直接定位它所存储的位置,若该处没有其他元素,则直接保存。若该处已经有元素存在,就调用equals方法来匹配这两个元素是否相同,相同则不存,不同则链到后面(如果是链地址法)。
先调用hashCode,唯一则存储,不唯一则再调用equals,结果相同则不再存储,结果不同则散列到其他位置。因为hashCode效率更高(仅为一个int值),比较起来更快。
HashMap#put源码
hash是key的hash值,当该hash对应的位置已有元素时会执行以下代码(hashCode相同)
if (p.hash == hash && ((k = p.key) == key || (key != null && key.equals(k))))
e = p;
如果equals返回结果相同,则值一定相同,不再存入。
如果重写equals不重写hashCode会怎样
两个值不同的对象的hashCode一定不一样,那么执行equals,结果为true,HashSet或HashMap的键会放入值相同的对象。
话不多说,直接上例子,~~~
首先我们只重写equals()方法
public class Student {
private String name;
private int age;
private String QQ;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return age == student.age &&
Objects.equals(name, student.name) &&
Objects.equals(QQ, student.QQ);
}
看我们的测试类
public class Test {
public static void main(String[] args) {
Student student = new Student();
Student student2 = new Student();
System.out.println(student.equals(student2)); //true
System.out.println(student.hashCode()); //356573597
System.out.println(student2.hashCode()); //1735600054
HashMap map = new HashMap();
map.put(student,"123");
map.put(student2,"456");
System.out.println(map.get(student));
System.out.println(map.get(student2));
}
}
依次输出
true
356573597 student 的hashcode值
1735600054 student 2的hashcode值
123
456
是否出现矛盾???
用equals比较说明对象相同,但是在HashMap中却以不同的对象存储(没有重写hascode值,两个hascode值,在他看来就是两个对象)。
到底这两个对象相等不相等????
说明必须重写hashCode()的重要性,
接下来重写重写equals方法和hashCode方法,再比较
public class Student {
private String name;
private int age;
private String QQ;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return age == student.age &&
Objects.equals(name, student.name) &&
Objects.equals(QQ, student.QQ);
}
@Override
public int hashCode() {
return Objects.hash(name, age, QQ);
}
}
测试类
public class Test {
public static void main(String[] args) {
Student student = new Student();
Student student2 = new Student();
System.out.println(student.equals(student2)); //true
System.out.println(student.hashCode()); // 29791
System.out.println(student2.hashCode()); // 29791
HashMap map = new HashMap();
map.put(student,"123");
map.put(student2,"456");
System.out.println(map.get(student)); //456
System.out.println(map.get(student2)); //456
}
}
依次输出
true
29791 //相同的对象
29791
456 //说明以一个值key存储,相同的值
456
看到这里,同学 你懂了吗?还不懂,可以自己实现一遍代码。
最后
领取专属 10元无门槛券
私享最新 技术干货