【问题标题】:Hashcode & equals implementationHashcode & equals 实现
【发布时间】:2014-08-12 09:42:16
【问题描述】:

我正在编写一些代码来演示equals和hashcode,对于我的实现,我使用了用户示例:

public class User {
    private String name;
    private String pass;
    //...
    @Override
    public boolean equals(Object obj) {
        if (obj == null) { return false; }
        if (obj == this) { return true; }
        if (obj.getClass() != this.getClass()) {
            return false;
        }
        User rhs = (User) obj;

        EqualsBuilder eb = new EqualsBuilder();
        eb.append(this.getName(), rhs.getName());
        //eb.append(this.getPass(), rhs.getPass());
        return eb.isEquals();
    }
    @Override
    public int hashCode() {
        HashCodeBuilder hcb = new HashCodeBuilder(17, 37);
        hcb.append(this.getName());
        hcb.append(this.getPass());
        return hcb.toHashCode();
    }
    //...
    public static void main(String[] args) {

        User u1 = new User("foo","foo1");
        User u2 = new User("bar","bar1");
        System.out.println(u1.equals(u2));
        System.out.println(u1.hashCode() + " ?= " + u2.hashCode());
        User u3 = new User("foo","foo1");
        User u4 = new User("foo","bar1");
        System.out.println(u3.equals(u4));
        System.out.println(u3.hashCode() + " ?= " + u4.hashCode());

    }
}

输出:

false
2128613651 ?= 2129111967
true
2128615478 ?= 2214545177

我认为我做错了,因为我的对象现在可以相等但具有不同的哈希码(我知道这很糟糕),但我想让我的用户只有在他们的名字也相等时才相等..而不是当他们有名字并且通过等于时。

我怎样才能尊重约定并拥有我想要实现的目标? 感谢您的帮助/澄清:)

【问题讨论】:

  • 你的 equals() 没有参数?我猜是复制粘贴问题,请修复
  • 是的,对不起。由 TheLostMind 修复,非常感谢。
  • The conventionswhat you want to achieve 有点矛盾

标签: java comparison equals hashcode apache-commons-lang


【解决方案1】:

一般来说,如果您的 equals() 方法中不存在某个字段,则不应在您的 hashCode() 方法中引用它。

这可确保您的 hashcode() 结果不会比您的 equals() 结果更频繁地更改。考虑将您的方法更改为:

@Override
public int hashCode() {
    HashCodeBuilder hcb = new HashCodeBuilder(17, 37);
    hcb.append(this.getName());
    return hcb.toHashCode();
}

话虽如此,创建一个非直观的equals() 方法并不是一个好主意。我自然会假设您的方法也会考虑密码,就像您未来的许多维护者一样。如果不进行真正的相等测试,单元测试可能更难编写。考虑创建自己的方法是否更好,例如

public boolean usernameEquals(User other) {
  ...
}

【讨论】:

  • 非常感谢您的澄清和建议 =)
  • 我不会实现 usernameEquals,我将使用 compareTo 方法仅按我认为的名称进行比较。
【解决方案2】:

所有相等的对象都具有相同的哈希码。但并非所有具有相同哈希码的对象都是相等的。

您在 hascode 方法中使用的所有字段都应该在您的 equals 方法中使用。

【讨论】:

    【解决方案3】:

    我不会说你做错了。 就合约而言,如果 2 个对象相等,那么它们应该具有相同的 hashCode。如果 2 个对象具有相同的 hashCode,则它们不必相等

    如果您将 2 个用户实例的相等性定义为 - 它们相等,如果它们的名称相等,那么您就可以开始了。就 hashCodes 而言,你是对的,因为如果 2 个对象的 hashCodes 不相等,那么对象就不相等。

    顺便说一句,Duncan 完全正确地指出 创建一个非直观的 equals() 方法很少是个好主意

    【讨论】:

    • 很可能只是错字,因为他在里面使用了obj
    猜你喜欢
    • 1970-01-01
    • 2019-06-02
    • 1970-01-01
    • 1970-01-01
    • 2020-02-21
    • 1970-01-01
    • 2013-07-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多