Java中的 equals() 和 hashCode() 方法
Java.lang.object 定义了两个非常重要的方法:public boolean equals(Object obj) 和 public int hashCode()。
等于()方法
在Java中,equals() 方法用于比较两个对象的相等性。可以通过两种方式比较相等性:
- 浅比较: equals 方法的默认实现是在Java.lang.Object 类中定义的,它只是检查两个 Object 引用(比如 x 和 y)是否引用同一个 Object。即它检查x == y。由于 Object 类没有定义其状态的数据成员,因此也称为浅比较。
- 深度比较:假设一个类提供了自己的 equals() 方法实现,以便比较该类的对象和对象的状态。这意味着要相互比较对象的数据成员(即字段)。这种基于数据成员的比较称为深度比较。
句法 :
public boolean equals (Object obj)
// This method checks if some other Object
// passed to it as an argument is equal to
// the Object on which it is invoked.
Object 类的 equals() 方法的一些原则:如果某个其他对象等于给定对象,则遵循以下规则:
- Reflexive :对于任何参考值 a,a.equals(a) 应该返回 true。
- 对称:对于任何参考值 a 和 b,如果 a.equals(b) 应返回 true,则 b.equals(a) 必须返回 true。
- 传递性:对于任何参考值 a、b 和 c,如果 a.equals(b) 返回 true 并且 b.equals(c) 返回 true,则 a.equals(c) 应该返回 true。
- 一致:对于任何参考值 a 和 b,a.equals(b) 的多次调用始终返回 true 或始终返回 false,前提是没有修改对象上 equals 比较中使用的信息。
注意:对于任何非空引用值 a,a.equals(null) 应该返回 false。
// Java program to illustrate
// how hashCode() and equals() methods work
import java.io.*;
class Geek
{
public String name;
public int id;
Geek(String name, int id)
{
this.name = name;
this.id = id;
}
@Override
public boolean equals(Object obj)
{
// checking if both the object references are
// referring to the same object.
if(this == obj)
return true;
// it checks if the argument is of the
// type Geek by comparing the classes
// of the passed argument and this object.
// if(!(obj instanceof Geek)) return false; ---> avoid.
if(obj == null || obj.getClass()!= this.getClass())
return false;
// type casting of the argument.
Geek geek = (Geek) obj;
// comparing the state of argument with
// the state of 'this' Object.
return (geek.name == this.name && geek.id == this.id);
}
@Override
public int hashCode()
{
// We are returning the Geek_id
// as a hashcode value.
// we can also return some
// other calculated value or may
// be memory address of the
// Object on which it is invoked.
// it depends on how you implement
// hashCode() method.
return this.id;
}
}
//Driver code
class GFG
{
public static void main (String[] args)
{
// creating the Objects of Geek class.
Geek g1 = new Geek("aa", 1);
Geek g2 = new Geek("aa", 1);
// comparing above created Objects.
if(g1.hashCode() == g2.hashCode())
{
if(g1.equals(g2))
System.out.println("Both Objects are equal. ");
else
System.out.println("Both Objects are not equal. ");
}
else
System.out.println("Both Objects are not equal. ");
}
}
输出:
Both Objects are equal.
在上面的示例中,请参见以下行:
// if(!(obj instanceof Geek)) return false;--> avoid.-->(a)
我们使用了这条线而不是上面的线:
if(obj == null || obj.getClass()!= this.getClass()) return false; --->(y)
在这里,首先我们比较两个对象(即 g1 和 g2)上的哈希码,如果两个对象生成相同的哈希码,这并不意味着它们相等,因为不同对象的哈希码也可以相同,如果它们具有相同id(在这种情况下)。因此,如果两个对象的生成的哈希码值相等,那么我们将这两个对象与它们的状态进行比较,以便我们覆盖类中的 equals(Object) 方法。如果根据 equals(Object) 方法,两个对象具有相同的状态,则它们相等,否则不相等。如果不同的对象生成不同的哈希码值,性能会更好。
原因:引用obj也可以引用Geek子类的Object。 (b) 行确保如果传递的参数是 Geek 子类的对象,它将返回 false。但是,如果instanceof运算符条件发现传递的参数是 Geek 类的子类,则不会返回 false。读取 InstanceOf运算符。
hashCode() 方法
它以整数形式返回哈希码值。 Hashcode 值主要用于基于散列的集合,如 HashMap、HashSet、HashTable……等。这个方法必须在每个覆盖 equals() 方法的类中被覆盖。
句法 :
public int hashCode()
// This method returns the hash code value
// for the object on which this method is invoked.
hashCode 的一般合约是:
- 在应用程序执行期间,如果在同一个 Object 上多次调用 hashCode(),则它必须始终返回相同的 Integer 值,前提是没有修改 Object 上的equals(Object)比较中使用的信息。从应用程序的一次执行到同一应用程序的另一次执行,该整数值不必保持相同。
- 如果两个对象相等,根据equals(Object)方法,那么 hashCode() 方法必须在两个对象的每一个上产生相同的 Integer。
- 如果两个 Object 不相等,根据equals(Object)方法,这两个 Object 上的 hashCode() 方法产生的 Integer 值不一定是不同的。它可以是相同的,但在两个对象的每一个上生成不同的整数对于提高基于散列的集合(如 HashMap、HashTable 等)的性能更好。
注意:相等的对象必须产生相同的哈希码,只要它们相等,但是不相等的对象不需要产生不同的哈希码。
相关链接:在Java中覆盖相等
参考: JavaRanch