即使我重写equals(Object o),HashSet也不包含我的自定义对象

时间:2014-03-08 13:09:56

标签: java

为什么这个程序false的输出?我期待true作为n对象初始化与我正在检查的相同字符串。

public class Test {
    public static void main(String[] args) {
        Name n = new Name("jyoti", "meher");
        Set<Name> s = new HashSet();
        s.add(n);
        System.out.println(s.contains(new Name("jyoti", "meher")));
    }
}

class Name {
    String name, title;

    public Name(String name, String title) {
        this.name = name;
        this.title = title;
    }

    public boolean equals(Object o) {
        if (!(o instanceof Name)) {

            return false;
        }
        Name n = (Name) o;
        return n.name.equals(name) && n.title.equals(title);
    }
}

5 个答案:

答案 0 :(得分:11)

您也必须覆盖hashCode(),而不仅仅是equals()

答案 1 :(得分:4)

要获得正确的输出,您需要覆盖名称类

中的hashCode()方法

答案 2 :(得分:2)

如果两个对象具有不同的hashCode值,则HashSet将认为它们不相等。

每当你覆盖equals时,你也应该覆盖hashCode()以确保它是一致的。在处理依赖哈希代码分发对象的HashSetHashMap时,这一点尤为重要。

您可以使用hashCode的以下(非最佳)实现来使用您的代码:

@Override
public int hashCode() {
    return 1;
}

这会强制HashSet在比较equals()个对象时使用Name方法。如果在生成哈希码时同时使用nametitle,则必须使用equals方法的次数会减少。

答案 3 :(得分:1)

在Name类中,equal和hashcode方法都应该覆盖。所以输出将为true。

答案 4 :(得分:0)

您应该重写equals()和hashcode()方法,以确保合同得到满足,将您的对象用作HashSet和HashMap等实现中的键。

您已正确覆盖了等号。您也可以覆盖哈希码,如下所示

@Override
public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result
            + ((name == null) ? 0 : name.hashCode());
    result = prime * result + id;
    result = prime * result
            + ((title == null) ? 0 : title.hashCode());
    return result;
}  

重写哈希码有助于根据哈希码将对象存储在不同的插槽中,从而加快搜索速度。

希望这有帮助