HashSet contains() 方法

8
我执行了以下代码,发现输出为false
import java.util.Set;
import java.util.HashSet;

public class Name {
    private String first, last;

    public Name(String first, String last) {
        this.first = first;
        this.last = last;
    }

    public boolean equals(Object o) {
        if (!(o instanceof Name))
            return false;
        Name n = (Name) o;
        return n.first.equals(first) && n.last.equals(last);
    }

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

我想知道它的行为方式以及为什么输出结果是 false


8
你没有覆盖重写 hashCode 方法。 - Jon Skeet
6个回答

7
您需要在重写equals()方法的同时,也要重写hashCode()方法。这两个方法都用于HashSet的正确功能,因此如果您将一个class作为key,则必须在用户定义的类中进行重写,否则将使用Object类的hashCode(),并且没有两个不同的objects可以被视为相同的,因为它们的hashCode()总是不同的,并且在contains()的情况下肯定会始终返回false。请注意保留HTML标记。

@babanna 如果它解决了你的疑惑,你可以将其标记为正确。 - AnkeyNigam

3
任何基于哈希的Java数据结构实现(集合)都是基于两个方面检查重复的:
1:如果equals方法对已经存储在集合中的任何元素返回true。
2:如果hashCode方法对已经存储在集合中的任何元素返回相同的整数值。
所以在您的情况下,您没有覆盖hashCode方法,这意味着它将尝试使用Object类的默认实现来检查hashCode相等性,而这个实现不知道您的last和first变量。
希望这可以帮助您。

3
为了让一个HashSet(或任何HashMap)正确地定位到你的对象,你需要覆盖hashCode()方法,使得相等的两个对象具有相同的hashCode值。这通常的做法如下所示(假设firstlast不能为null,就像你的equals方法一样):
@Override
public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + first.hashCode();
    result = prime * result + last.hashCode();
}

1
< p > 在覆盖equals()方法的每个类中,都必须覆盖hashCode()方法。如果不这样做,将违反Object.hashCode()的一般契约,这将导致您的类无法与所有基于哈希的集合(包括HashMap、HashSet和Hashtable)正常配合使用。

来自Joshua Bloch的《Effective Java》


将代码格式放入每行代码的四个空格中。 - jsingh

1
你的 equals() 方法没问题,但是你忘记了重写 hashCode() 方法,只需要重写 hashCode() 方法就可以了。而且不要忘记你总是需要重写 equals() 和 hashCode() 或者两个都不重写才能得到正确的行为。如果你计划将对象用作哈希机制中的键,则必须同时重写它们两个。
@Override
public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + ((first == null) ? 0 : first.hashCode());
    result = prime * result + ((last == null) ? 0 : last.hashCode());
    return result;
}

0

您还可以查看代码的执行方式。

  1. 当您尝试在集合中添加元素时,它会调用哈希码并获取桶。

  2. 一旦从哈希码获取哈希值,重载的equals方法将会为所有具有相同哈希令牌的对象运行。

希望这能帮到您。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接