HashSet contains() 方法

HashSet contains() method

我执行了下面的代码,发现输出是 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

您还需要覆盖 hashCode() 方法以及 equals()。这两种方法都用于 HashSet 的正常功能,因此如果您将 class 作为a key, else hashCode() of Object class 正在被使用,没有两个不同的 objects 可以被认为与他们的 hashCode() 总是一样会有所不同,并且肯定会 return false总是 contains()

为了让 HashSet(或 HashMap,就此而言)正确定位您的对象,您需要覆盖 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();
}

你的equals()方法没问题,但是你错过了覆盖hashCode()方法,直接覆盖hashCode()方法就可以了。并且不要忘记您总是需要覆盖它们的 equals() and hashCode() 或 none 以获得正确的行为。如果您打算将您的对象用作哈希机制中的键,那么您必须覆盖它们。

@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;
}

您必须在覆盖 equals() 的每个 class 中覆盖 hashCode()。不这样做将导致违反 Object.hashCode() 的一般合同,这将阻止您的 class 与所有基于散列的集合一起正常运行,包括 HashMap, HashSet, and Hashtable.

来自 Effective Java,作者:Joshua Bloch

Java 中任何基于 Hash 的数据结构实现(集合)基于两件事检查重复:

1 : if equals 方法 returns true 对于已经存储在集合中的任何元素。

2 : 如果 hashCode 方法 returns same integer value 用于已存储在集合中的任何元素。

所以在你的情况下你没有覆盖 hashCode 方法,这意味着它会尝试使用 hashCode 方法默认实现 Object class 检查 hashCode 相等性,它不知道你的 lastfirst 变量。

希望对您有所帮助。

您还可以看到您的代码将如何执行。

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

  2. 一旦您从散列码中获得散列值,对于所有具有相同散列令牌的人,覆盖的等于将是 运行。

希望对您有所帮助。