HashSet contains() 方法

Posted

技术标签:

【中文标题】HashSet contains() 方法【英文标题】:HashSet contains() method 【发布时间】:2015-10-06 20:40:34 【问题描述】:

我执行了下面的代码,发现输出是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 【参考方案1】:

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

来自 Effective Java,作者:Joshua Bloch

【讨论】:

输入代码格式,每行代码给四个空格【参考方案2】:

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

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

    一旦您从哈希码中获得哈希值,就会为所有拥有相同哈希令牌的人运行覆盖的等号。

希望这会有所帮助。

【讨论】:

【参考方案3】:

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

1 : 如果equals 方法为已存储在集合中的任何元素返回true

2 : 如果hashCode 方法为已存储在集合中的任何元素返回same integer value

因此,在您的情况下,您没有覆盖 hashCode 方法,这意味着它将尝试使用 Object 类的 hashCode 方法默认实现来检查 hashCode 是否相等,该类不知道您的 lastfirst 变量。

希望对你有帮助。

【讨论】:

【参考方案4】:

您的equals() 方法没问题,但是您错过了覆盖hashCode() 方法,只需覆盖hashCode() 方法即可。并且不要忘记您总是需要同时覆盖 equals() and 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;

【讨论】:

【参考方案5】:

您还需要覆盖hashCode() 方法以及equals()。这两种方法都用于HashSet 的正确功能,因此如果您将class 设置为key,则必须在用户定义的类 中覆盖,否则hashCode() of @ 987654327@ 类正在被使用,没有两个不同的objects 可以被视为相同,因为它们的hashCode() 总是不同的,并且在contains() 的情况下肯定会返回falsealways。

【讨论】:

@babanna 如果它消除了你的疑虑,你可以将其标记为正确。【参考方案6】:

为了使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();

【讨论】:

以上是关于HashSet contains() 方法的主要内容,如果未能解决你的问题,请参考以下文章

慎用ArrayList的contains方法,使用HashSet的contains方法代替

HashSet——add remove contains方法底层代码分析(hashCode equals 方法的重写)

Arraylist中contains方法底层实现解读与HashSet自定义类型去重效果的简述(接上一篇)

217. Contains Duplicate

Java Hashset.contains() 产生神秘的结果

True or False? and WHY??? Java HashSet Contains