定义:通过某个特征值来判断两个对象是否“等价”,当这两个对象等价时,判断结果为true,否则结果为false。
-
默认源码 : 默认请情况下Object 对象做对象内存地址比较;
public boolean equals(Object obj) { return (this == obj); } -
重写equals逻辑 : 重写后对象进行值比较,更改比较条件
@Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; User user = (User) o; return age == user.age && id == user.id && Objects.equals(name, user.name); }
三、重写equals为何要重写hashcode==比较的是2个对象的地址
重写equals为何要重写hashcode的文章多如繁星,每次看这都懂,过后就忘记,今日手工写点案例进行测试说为何重写equals为何要重写hashcode,废话不多说直接上代码。
-
不重写equals和hashcode方法
案例:
public class User { private String name; private int age; private long id; public User(String name, int age, long id) { this.name = name; this.age = age; this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public long getId() { return id; } public void setId(long id) { this.id = id; } // @Override // public boolean equals(Object o) { // if (this == o) return true; // if (o == null || getClass() != o.getClass()) return false; // User user = (User) o; // return age == user.age && // id == user.id && // Objects.equals(name, user.name); // } // // @Override // public int hashCode() { // return Objects.hash(name, age, id); // } }public class JavaCoding { public static void main(String[] args) { User user1 = new User("A", 11, 1L); User user2 = new User("A", 11, 1L); System.out.println("equals result : " + user1.equals(user2)); System.out.println("== result : " + (user1 == user2)); Map
输出结果:
equals result : false
== result : false
map.get(user1) : 111
map.get(user2) : 222
com.example.coding.pojo.User@1d81eb93 222
com.example.coding.pojo.User@4e50df2e 111
案例分析:
当没有重写equals和hascode时,上述案例中的user1和user2是通过new关键字创建出的两个不同的对象,其引用地址也完全不相同,equals和==此时均为比较对象引用地址,所以输出均为false结果不相同。
而使用对象做map KEY时,会调用对象的hashcode方法分配存储位置地址,由于对象的引用地址不相同,所以hash后的值也不同,最终会存放在不同的位置上,因此输出时可以完整输出map中的两个元素
-
重写equals不重写hashcode方法
public class User { private String name; private int age; private long id; public User(String name, int age, long id) { this.name = name; this.age = age; this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public long getId() { return id; } public void setId(long id) { this.id = id; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; User user = (User) o; return age == user.age && id == user.id && Objects.equals(name, user.name); } // @Override // public int hashCode() { // return Objects.hash(name, age, id); // } }public class JavaCoding { public static void main(String[] args) { User user1 = new User("A", 11, 1L); User user2 = new User("A", 11, 1L); System.out.println("equals result : " + user1.equals(user2)); System.out.println("== result : " + (user1 == user2)); Map输出结果:
equals result : true
== result : false
map.get(user1) : 111
map.get(user2) : 222
com.example.coding.pojo.User@1d81eb93 222 com.example.coding.pojo.User@4e50df2e 111
案例分析:
1、由于重写equlas方法,因此对象做equals比较时实际是比较对象中元素的值,上述两个对象的值完全相同,所以为true
2、== 由于是比较对象的栈中的引用地址,而对象是通过new的方式创建,因此地址是不相同的,所以为false
3、而使用对象做map KEY时,会调用对象的hashcode方法分配存储位置地址,由于对象的引用地址不相同,所以hash后的值也不同,最终会存放在不同的位置上,因此输出时可以完整输出map中的两个元素
-
重写equals和hashcode方法
public class User { private String name; private int age; private long id; public User(String name, int age, long id) { this.name = name; this.age = age; this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public long getId() { return id; } public void setId(long id) { this.id = id; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; User user = (User) o; return age == user.age && id == user.id && Objects.equals(name, user.name); } @Override public int hashCode() { return Objects.hash(name, age, id); } }public class JavaCoding { public static void main(String[] args) { User user1 = new User("A", 11, 1L); User user2 = new User("A", 11, 1L); System.out.println("equals result : " + user1.equals(user2)); System.out.println("== result : " + (user1 == user2)); Map输出结果:
equals result : true
== result : false
map.get(user1) : 222
map.get(user2) : 222
com.example.coding.pojo.User@169b6 222
案例分析:
1、由于重写equlas方法,因此对象做equals比较时实际是比较对象中元素的值,上述两个对象的值完全相同,所以为true
2、== 由于是比较对象的栈中的引用地址,而对象是通过new的方式创建,因此地址是不相同的,所以为false
3、由于重写的了hashcode方法(实际对对象的数据进行hash),对象user1和user2中的数据完全相同,在map插入的时候两个对象hash出来的值也相同,因此后查询的user2和覆盖先查询的uesr1的value值,因此输出结果中会出现user2对应的map结果值222



