在 Java 中重写 Hashcode 函数

Rupam Yadav 2023年10月12日
  1. 为什么我们要重写 hashcode() 方法
  2. 重写 Java 中的 hashcode() 方法
在 Java 中重写 Hashcode 函数

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

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

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

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

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

我们使用 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 作为参数并返回 booleanequals() 方法。

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

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

为了更好地说明这一点,我们创建了一个 HashSet(),它返回一个 Set<DummyClass> 类型的对象,并使用 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<DummyClass> 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<DummyClass> 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]

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

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

输出:

10
10
作者: Rupam Yadav
Rupam Yadav avatar Rupam Yadav avatar

Rupam Saini is an android developer, who also works sometimes as a web developer., He likes to read books and write about various things.

LinkedIn