定义区别
- equals() :
- hashCode():
- 作用是获取哈希码,也称为散列码;
- 它实际上是返回一个 int 整数。
- 这个哈希码的作用是确定对象在哈希表中的索引位置。
一个类本身不创建散列表
- 该类的 hashCode() 和 equals() 没有关系,equals() 用来比较该类的两个对象是否相等,而 hashCode() 则根本没有任何作用。
- equals() 相等的情况下,hashCode() 也不一定相等。
/**
* @desc 比较equals()返回true和返回false时,hashCode()的值。
*/
public class NormalHashCodeTest{
public static void main(String[] args) {
// 新建2个相同内容的Person对象,
// 再用equals比较它们是否相等
Person p1 = new Person("eee", 100);
Person p2 = new Person("eee", 100);
Person p3 = new Person("aaa", 200);
System.out.printf("p1.equals(p2) : %s; p1(%d) p2(%d)\n", p1.equals(p2), p1.hashCode(), p2.hashCode());
System.out.printf("p1.equals(p3) : %s; p1(%d) p3(%d)\n", p1.equals(p3), p1.hashCode(), p3.hashCode());
}
/* Person类 */
private static class Person {
int age;
String name;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String toString() {
return name + " - " +age;
}
/* 覆盖equals方法 */
public boolean equals(Object obj){
if(obj == null){
return false;
}
//如果是同一个对象返回true,反之返回false
if(this == obj){
return true;
}
//判断是否类型相同
if(this.getClass() != obj.getClass()){
return false;
}
/* 比较name和age的值 */
Person person = (Person)obj;
return name.equals(person.name) && age==person.age;
}
}
}
p1.equals(p2) : true; p1(1169863946) p2(1901116749)
p1.equals(p3) : false; p1(1169863946) p3(2131949076)
- 从结果也可以看出:p1 和 p2 相等的情况下,hashCode() 也不一定相等。
一个类本身会创建散列表
- 该类的 hashCode() 和 equals() 是有关系的。比如 HashSet, Hashtable, HashMap 等等
- 如果两个对象相等,那么它们的 hashCode() 一定相等。这里的相等是指,通过equals()比较两个对象时返回true。
- 如果两个对象 hashCode() 相等,但它们并不一定相等。因为在散列表中,hashCode()相等,即两个键值对的哈希值相等。然而哈希值相等,并不一定能得出键值对相等。补充说一句:“两个不同的键值对,哈希值相等”,这就是哈希冲突。
- 在这种情况下。若要判断两个对象是否相等,除了要覆盖 equals() 之外,也要覆盖hashCode() 函数。否则,equals() 无效。
- 举例
- 创建 Person 类的 HashSet 集合,必须同时覆盖 Person 类的 equals() 和 hashCode() 方法。
只是覆盖 equals() 方法
- 我们会发现,equals() 方法没有达到我们想要的效果。
import java.util.*;
import java.lang.Comparable;
/**
* @desc 比较equals() 返回true 以及 返回false时, hashCode()的值。
*
*/
public class ConflictHashCodeTest1{
public static void main(String[] args) {
// 新建Person对象,
Person p1 = new Person("eee", 100);
Person p2 = new Person("eee", 100);
Person p3 = new Person("aaa", 200);
// 新建HashSet对象
HashSet set = new HashSet();
set.add(p1);
set.add(p2);
set.add(p3);
// 比较p1 和 p2, 并打印它们的hashCode()
System.out.printf("p1.equals(p2) : %s; p1(%d) p2(%d)\n", p1.equals(p2), p1.hashCode(), p2.hashCode());
// 打印set
System.out.printf("set:%s\n", set);
}
/**
* @desc Person类。
*/
private static class Person {
int age;
String name;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String toString() {
return "("+name + ", " +age+")";
}
/**
* @desc 覆盖equals方法
*/
@Override
public boolean equals(Object obj){
if(obj == null){
return false;
}
//如果是同一个对象返回true,反之返回false
if(this == obj){
return true;
}
//判断是否类型相同
if(this.getClass() != obj.getClass()){
return false;
}
Person person = (Person)obj;
return name.equals(person.name) && age==person.age;
}
}
}
p1.equals(p2) : true; p1(1169863946) p2(1690552137)
set:[(eee, 100), (eee, 100), (aaa, 200)]
- 结果分析:
- 这是因为虽然 p1 和 p2 的内容相等,但是它们的 hashCode() 不等;所以,HashSet 在添加 p1 和 p2 的时候,认为它们不相等。
- 我们重写了Person的equals()。但是,很奇怪的发现:HashSet中仍然有重复元素:p1 和 p2。为什么会出现这种情况呢?
同时覆盖 equals() 和 hashCode() 方法呢?
import java.util.*;
import java.lang.Comparable;
/**
* @desc 比较equals() 返回true 以及 返回false时, hashCode()的值。
*
*/
public class ConflictHashCodeTest2{
public static void main(String[] args) {
// 新建Person对象,
Person p1 = new Person("eee", 100);
Person p2 = new Person("eee", 100);
Person p3 = new Person("aaa", 200);
Person p4 = new Person("EEE", 100);
// 新建HashSet对象
HashSet set = new HashSet();
set.add(p1);
set.add(p2);
set.add(p3);
// 比较p1 和 p2, 并打印它们的hashCode()
System.out.printf("p1.equals(p2) : %s; p1(%d) p2(%d)\n", p1.equals(p2), p1.hashCode(), p2.hashCode());
// 比较p1 和 p4, 并打印它们的hashCode()
System.out.printf("p1.equals(p4) : %s; p1(%d) p4(%d)\n", p1.equals(p4), p1.hashCode(), p4.hashCode());
// 打印set
System.out.printf("set:%s\n", set);
}
/**
* @desc Person类。
*/
private static class Person {
int age;
String name;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String toString() {
return name + " - " +age;
}
/**
* @desc重写hashCode
*/
@Override
public int hashCode(){
int nameHash = name.toUpperCase().hashCode();
return nameHash ^ age;
}
/**
* @desc 覆盖equals方法
*/
@Override
public boolean equals(Object obj){
if(obj == null){
return false;
}
//如果是同一个对象返回true,反之返回false
if(this == obj){
return true;
}
//判断是否类型相同
if(this.getClass() != obj.getClass()){
return false;
}
Person person = (Person)obj;
return name.equals(person.name) && age==person.age;
}
}
}
p1.equals(p2) : true; p1(68545) p2(68545)
p1.equals(p4) : false; p1(68545) p4(68545)
set:[aaa - 200, eee - 100]
- 结果分析:
- 这下,equals() 生效了,HashSet 中没有重复元素。
- 比较 p1 和 p4,我们发现:虽然它们的 hashCode() 相等;但是,通过 equals() 比较它们返回 false。所以,p1 和 p4 被视为不相等。
- 比较 p1 和 p2,我们发现:它们的 hashCode() 相等,通过 equals() 比较它们也返回 true。所以,p1 和 p2 被视为相等。