首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >LinkedHashSet: hashCode()和hashCode()匹配,但是hashCode()不匹配

LinkedHashSet: hashCode()和hashCode()匹配,但是hashCode()不匹配
EN

Stack Overflow用户
提问于 2011-11-04 10:17:37
回答 3查看 5.8K关注 0票数 1

如何能够做到以下几点:

代码语言:javascript
复制
void contains(LinkedHashSet data, Object arg) {
    System.out.println(data.getClass()); // java.util.LinkedHashSet
    System.out.println(arg.hashCode() == data.iterator().next().hashCode()); // true
    System.out.println(arg.equals(data.iterator().next())); // true
    System.out.println(new ArrayList(data).contains(arg)); // true
    System.out.println(new HashSet(data).contains(arg)); // true
    System.out.println(new LinkedHashSet(data).contains(arg)); // true (!)
    System.out.println(data.contains(arg)); // false
}

我做错了什么吗?

显然,这种情况并不总是发生(如果您创建了一组琐碎的对象,就不会再现它)。但在我的情况下,这种情况总是发生在更复杂的arg类中。

编辑:我没有在这里定义arg的主要原因是它是相当大的类,Eclipse生成的hashCode跨越20行,equals的长度是它的两倍。我不认为这是相关的,只要它们对这两个物体是相等的。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2011-11-04 10:42:21

当您构建自己的对象并计划在集合中使用它们时,您应该始终覆盖以下方法:

代码语言:javascript
复制
boolean equals(Object o);
int hashCode();

equals的默认实现检查对象是否指向同一个对象,而您可能希望重新定义它以检查内容。

根据合理的实际情况,类对象定义的hashCode方法确实返回不同对象的不同整数。要遵守规则,对象的hashCode与另一个对象的规则应该是相同的,因此您还必须重新定义hashCode。

编辑:我原以为会有错误的hashCodeequals实现,但自从您的回答之后,您就发现在将密钥添加到HashSet或HashMap之后,您正在对它们进行变异。

将对象添加到散列集合时,将计算其hashCode并将其映射到集合中的物理位置。

如果一些用于计算hashCode的字段被更改,那么hashCode本身就会改变,因此HashSet实现将变得混乱。当它试图获取对象时,它将查看另一个物理位置,而不会找到该对象。但是,如果枚举集合,则该对象仍然存在。

出于这个原因,请始终使HashMap或HashSet键。

票数 4
EN

Stack Overflow用户

发布于 2011-11-04 11:18:34

明白了。一旦你知道了,答案是如此明显,你只能在尴尬中脸红。

代码语言:javascript
复制
static class MyObj {
    String s = "";

    @Override
    public int hashCode() {
        return s.hashCode();
    }

    @Override
    public boolean equals(Object obj) {
        return ((MyObj) obj).s.equals(s);
    }
}

public static void main(String[] args) {
    LinkedHashSet set = new LinkedHashSet();
    MyObj obj = new MyObj();
    set.add(obj);
    obj.s = "a-ha!";
    contains(set, obj);
}

这就足以可靠地复制它了。

说明:Thou从不修改用于hashCode()!的字段

票数 1
EN

Stack Overflow用户

发布于 2011-11-04 10:31:59

你的问题好像漏掉了什么。我做了一些猜测:

代码语言:javascript
复制
private void testContains() {
  LinkedHashSet set = new LinkedHashSet();
  String hello = "Hello!";
  set.add(hello);
  contains(set, hello);
}

void contains(LinkedHashSet data, Object arg) {
  System.out.println(data.getClass()); // java.util.LinkedHashSet
  System.out.println(arg.hashCode() == data.iterator().next().hashCode()); // true
  System.out.println(arg.equals(data.iterator().next())); // true
  System.out.println(new ArrayList(data).contains(arg)); // true
  System.out.println(new HashSet(data).contains(arg)); // true
  System.out.println(new LinkedHashSet(data).contains(arg)); // true (!)
  System.out.println(data.contains(arg)); // true (!!)
}

编辑:跟踪不断变化的问题!

除了第一次输出之外,我仍然得到了“真”。请更具体地说明"arg“参数的类型。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8007723

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档