返回

EqualsAndHashCode组合拳,助你深入理解Java对象比较与散列

后端

对象比较与散列:Java程序员的必备利器

对象比较:equals() 方法

对象比较对于确定两个对象是否相等至关重要。在 Java 中,我们使用 equals() 方法来实现此功能。默认情况下,equals() 方法使用 == 运算符比较对象的内存地址,如果相等则返回 true,否则返回 false

为了满足不同的比较需求,我们可以重写 equals() 方法。重写时,我们需要根据对象的属性来比较是否相等。例如,对于 Person 对象,我们可以根据姓名、年龄和性别来比较。

重写 equals() 方法的注意事项:

  • 反身性: 如果 a.equals(b)true,则 b.equals(a) 也必须为 true
  • 对称性: 如果 a.equals(b)true,则 b.equals(a) 也必须为 true
  • 传递性: 如果 a.equals(b)true,且 b.equals(c)true,则 a.equals(c) 也必须为 true
  • 一致性: 如果 ab 是同一个对象,那么多次调用 a.equals(b) 都必须返回 true
  • 非空性: equals() 方法不应接受 null 作为参数。如果其中一个参数为 null,则应该抛出 NullPointerException 异常。

散列:hashCode() 方法

散列是一种将对象存储在哈希表中的技术,允许我们以 O(1) 的时间复杂度查找对象。散列通过 hashCode() 方法实现。

hashCode() 方法的作用是计算对象的散列码。散列码是一个整数,代表对象的唯一标识符。如果两个对象相等,则它们的散列码也必须相等。

重写 hashCode() 方法的注意事项:

  • 一致性: 如果 ab 是同一个对象,那么多次调用 a.hashCode() 都必须返回相同的散列码。
  • 非空性: hashCode() 方法不应接受 null 作为参数。如果参数为 null,则应该抛出 NullPointerException 异常。

equals() 和 hashCode() 的组合拳

equals()hashCode() 是 Java 中对象比较和散列的基础。它们密切相关,在重写 equals() 方法时,通常也需要重写 hashCode() 方法。

原因是,如果两个对象相等,那么它们的散列码也必须相等。如果不这样做,就会导致哈希表中出现冲突,降低查找效率。

示例代码:

public class Person {
    private String name;
    private int age;
    private Gender gender;

    // equals() 方法的重写
    @Override
    public boolean equals(Object obj) {
        if (obj == this) {
            return true;
        }

        if (!(obj instanceof Person)) {
            return false;
        }

        Person other = (Person) obj;

        return this.name.equals(other.name) &&
                this.age == other.age &&
                this.gender == other.gender;
    }

    // hashCode() 方法的重写
    @Override
    public int hashCode() {
        int result = 17;
        result = 31 * result + name.hashCode();
        result = 31 * result + age;
        result = 31 * result + gender.hashCode();
        return result;
    }
}

常见问题解答

  1. 为什么我们需要重写 equals()hashCode() 方法?

    为了满足不同的比较和散列需求。默认的实现可能不够充分。

  2. 如果不重写 hashCode() 方法会怎样?

    可能会导致哈希表中出现冲突,降低查找效率。

  3. 如何确保 equals()hashCode() 方法的一致性?

    equals() 方法中,使用 this 引用当前对象,在 hashCode() 方法中,使用最终字段或不可变字段计算散列码。

  4. equals()== 运算符有什么区别?

    == 比较对象的内存地址,而 equals() 比较对象的属性。

  5. 什么时候应该使用 equals(),什么时候应该使用 hashCode()

    equals() 用于确定两个对象是否相等,而 hashCode() 用于计算对象的散列码。