在 Java 中重写 Hashcode 函数

为什么我们要重写 hashcode() 方法

重写 Java 中的 hashcode() 方法

Java 中的 hashcode 是一个使用散列算法并返回一个表示对象的整数值的函数。hashcode() 是 Object 类的一部分,这意味着该函数可用于继承 Object 类的每个类。

本文将展示我们如何重写 hashcode() 方法来提供我们的实现。

为什么我们要重写 hashcode() 方法

在我们继续重写 hashcode() 函数之前,我们应该了解为什么我们需要重写这个方法。要记住的重要一点是 equals() 和 hashcode() 方法一起使用,并且当 equals() 函数被重写时,通常强制重写 hashcode() 方法。这是因为 hashcode() 表示如果对象相等,则它们的哈希码也必须相等。

为了实际理解重写 hashcode() 方法背后的动机,我们创建了一个示例,其中包含两个名为 HashCodeExample 和 DummyClass 的类。在 DummyClass 中,我们提供了一个设置 abc 变量的简单构造函数。现在在 HashCodeExample 类中,我们创建 DummyClass 类的两个实例,并将它们命名为 dummyClass1 和 dummyclass2,在它们的构造函数中具有相同的值。

我们使用 equals() 方法比较两个实例,但输出显示它们不相等。

public class HashCodeExample {

public static void main(String[] args) {

DummyClass dummyClass1 = new DummyClass(10);

DummyClass dummyClass2 = new DummyClass(10);

System.out.println(dummyClass1.equals(dummyClass2));

}

}

class DummyClass {

int abc;

public DummyClass(int abc) {

this.abc = abc;

}

}

输出:

false

这是因为 Java 中的每个对象实例都有一个唯一的哈希码,我们可以通过在两个对象上调用 hashCode() 方法来检查它。输出显示两个对象的整数值不同。

System.out.println(dummyClass1.hashCode());

System.out.println(dummyClass2.hashCode());

输出:

2065951873

1791741888

为了解决不相等对象的问题,我们可以重写 equals() 函数并使用我们的实现。下面的代码与第一个程序相同,但我们重写了将 Object 作为参数并返回 boolean 的 equals() 方法。

在 equals() 函数中,我们将 Object 类型的参数 o 转换为 DummyClass 的类型,它返回 DummyClass 的实例。现在我们将 DummyClass 类的变量 abc 与作为参数传入方法的对象变量 abc 进行比较。

输出显示 dummyClass1.equals(dummyClass2) 的结果为 true,因为我们修改了默认实现以在实例的值相同时返回 true。

public class HashCodeExample {

public static void main(String[] args) {

DummyClass dummyClass1 = new DummyClass(10);

DummyClass dummyClass2 = new DummyClass(10);

System.out.println(dummyClass1.equals(dummyClass2));

}

}

class DummyClass {

int abc;

public DummyClass(int abc) {

this.abc = abc;

}

@Override

public boolean equals(Object o) {

DummyClass dummyClassObj = (DummyClass) o;

return this.abc == dummyClassObj.abc;

}

}

输出:

true

上述解决方案仅在我们比较值而不是哈希码时才有效,因为对象 dummyClass1 和 dummyClass2 的哈希码仍然不同。

为了更好地说明这一点,我们创建了一个 HashSet(),它返回一个 Set 类型的对象,并使用 add() 函数将两个 DummyClass 对象添加到其中。现在我们打印 Set 并在输出中得到两个具有不同引用的对象,这证明 DummyClass 对象具有不同的哈希码。

这是我们重写 hashcode() 函数以解决问题的地方,我们将在下面的下一个示例中看到。

import java.util.HashSet;

import java.util.Set;

public class HashCodeExample {

public static void main(String[] args) {

DummyClass dummyClass1 = new DummyClass(10);

DummyClass dummyClass2 = new DummyClass(10);

Set dummyClassSet = new HashSet<>();

dummyClassSet.add(dummyClass1);

dummyClassSet.add(dummyClass2);

System.out.println(dummyClassSet);

}

}

class DummyClass {

int abc;

public DummyClass(int abc) {

this.abc = abc;

}

@Override

public boolean equals(Object o) {

DummyClass dummyClass = (DummyClass) o;

return this.abc == dummyClass.abc;

}

}

输出:

[DummyClass@7b23ec81, DummyClass@6acbcfc0]

重写 Java 中的 hashcode() 方法

为了在 hashcode() 方法中使用我们的实现,我们首先重写 DummyClass 类中的 hashcode() 方法并返回类变量 abc 的值。现在哈希码被替换为 abc 的值。现在,如果我们打印 dummyClassSet,我们只会得到一个对象,因为哈希码或引用是相同的。

import java.util.HashSet;

import java.util.Set;

public class HashCodeExample {

public static void main(String[] args) {

DummyClass dummyClass1 = new DummyClass(10);

DummyClass dummyClass2 = new DummyClass(10);

Set dummyClassSet = new HashSet<>();

dummyClassSet.add(dummyClass1);

dummyClassSet.add(dummyClass2);

System.out.println(dummyClassSet);

}

}

class DummyClass {

int abc;

public DummyClass(int abc) {

this.abc = abc;

}

@Override

public boolean equals(Object o) {

DummyClass dummyClass = (DummyClass) o;

return this.abc == dummyClass.abc;

}

@Override

public int hashCode() {

return abc;

}

}

输出:

[DummyClass@a]

如果我们打印对象 dummyClass1 和 dummyClass2 的哈希码,我们会得到相同的哈希码。

System.out.println(dummyClass1.hashCode());

System.out.println(dummyClass2.hashCode());

输出:

10

10

Enjoying our tutorials? Subscribe to DelftStack on YouTube to support us in creating more high-quality video guides. Subscribe