简体   繁体   English

哈希码和等于实现

[英]Hashcode & equals implementation

I'm writing some code to demonstrate equals and hashcode, for my implementation I used User example : 我正在编写一些代码来演示equals和hashcode,对于我的实现,我使用了User示例:

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());

    }
}

Output: 输出:

false
2128613651 ?= 2129111967
true
2128615478 ?= 2214545177

I think I'm doing it wrong because my objects now can be equals but have a different hashcode (which is bad I know), but I want to make my Users equals only when their names are also equals.. And not when they have name AND pass equals. 我想我做错了,因为我的对象现在可以相等但具有不同的哈希码(我知道这很糟糕),但是我想仅当用户名也相等时才使用户相等。名称AND通行证等于。

How can I respect the conventions and have what I want to achieve? 我如何才能遵守这些约定,并实现自己的目标? Thanks for your help/clarification :) 感谢您的帮助/说明:)

Generally speaking, if a field is not present in your equals() method, you shouldn't reference it in your hashCode() method. 一般而言,如果equals()方法中不存在字段,则不应在hashCode()方法中引用该字段。

This ensures your hashcode() result will not change more often that your equals() result does. 这样可以确保您的hashcode()结果不会比equals()结果更频繁地更改。 Consider changing your method to: 考虑将您的方法更改为:

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

That being said, it's rarely a good idea to create a non-intuitive equals() method. 话虽如此,创建一个非直觉的equals()方法很少是一个好主意。 I would naturally assume your method would consider the password too, as might many of your future maintainers. 我自然会假设您的方法也将考虑密码,因为您将来的许多维护者也会考虑。 Unit tests may be harder to write if true equality testing isn't conducted. 如果不进行真正的相等性测试,则单元测试可能很难编写。 Consider whether it would be better to create your own method, eg 考虑创建自己的方法是否更好,例如

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

All objects that are equals have the same hashcode. 所有相等的对象具有相同的哈希码。 but not all object that have the same hashcode are equal. 但并非所有具有相同哈希码的对象都是相等的。

All field you use in your hascode method should to be used in your equals method. 您在hascode方法中使用的所有字段都应在equals方法中使用。

I wouldn't say that you are doing it wrong. 我不会说你做错了。 As far as the contract is concerned, If 2 objects are equal, then they should have the same hashCode. 就合同而言, 如果2个对象相等,则它们应具有相同的hashCode。 If 2 objects have the same hashCode, they need not be equal 如果2个对象具有相同的hashCode,则它们不必相等

If you define the equality of 2 User instances as - They are equal, if their names are equal , then you are good to go. 如果将2个User实例的相等性定义为- 它们相等,则如果它们的名称相等 ,那么您就可以了。 As far as the hashCodes are concerned, you are right, because if the hashCodes of 2 objects are not equal, then the objects are not equal. 就hashCodes而言,您是对的,因为如果2个对象的hashCodes不相等,则这些对象也不相等。

BTW Duncan is completely right in pointing out that it's rarely a good idea to create a non-intuitive equals() method BTW Duncan完全正确地指出, 创建非直观的equals()方法很少是一个好主意

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM