Java Hashcode&;平等执行

Java Hashcode&;平等执行,java,comparison,equals,hashcode,apache-commons-lang,Java,Comparison,Equals,Hashcode,Apache Commons Lang,我正在编写一些代码来演示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) { r

我正在编写一些代码来演示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
我认为我做得不对,因为我的对象现在可以是相等的,但有不同的哈希代码(我知道这很糟糕),但我想让我的用户只有在他们的名字也相等时才相等。。而不是当他们有name和pass相等时

我怎样才能尊重传统,实现我的目标?
感谢您的帮助/澄清:)

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


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

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


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

我不会说您做得不对。 就契约而言,如果两个对象相等,那么它们应该具有相同的哈希代码。如果两个对象具有相同的哈希代码,则它们不必相等

如果您将两个用户实例的相等定义为-它们相等,如果它们的名称相等,那么您就可以开始了。就哈希代码而言,您是对的,因为如果两个对象的哈希代码不相等,那么这些对象就不相等


顺便说一句,邓肯完全正确地指出,创建一个非直观的equals()方法很少是个好主意,我不会说你做得不对。 就契约而言,如果两个对象相等,那么它们应该具有相同的哈希代码。如果两个对象具有相同的哈希代码,则它们不必相等

如果您将两个用户实例的相等定义为-它们相等,如果它们的名称相等,那么您就可以开始了。就哈希代码而言,您是对的,因为如果两个对象的哈希代码不相等,那么这些对象就不相等


顺便说一句,Duncan完全正确地指出,创建一个非直观的equals()方法很少是一个好主意。一般来说,如果在
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) {
  ...
}

一般来说,如果在
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) {
  ...
}

您的equals()没有参数?我猜是复制粘贴问题,请修复是的,对不起。最后一点修正了,非常感谢。
约定
您想要实现的目标
有点矛盾,或者您的equals()没有参数?我猜是复制粘贴问题,请修复是的,对不起。由后脑勺修复,非常感谢。
约定
你想要实现的
几乎没有矛盾,很可能只是打字错误,因为他使用
obj
内部最有可能只是打字错误,因为他使用
obj
内部非常感谢你的澄清和保护=)我不会实现usernamequals,我将使用compareTo方法仅按名称进行比较。非常感谢您的澄清和protips=)我不会实现usernameEquals,我将使用compareTo方法仅按名称进行比较。