HashSet项目等于,但HashSet不包含

问题描述 投票:0回答:2

我有一个包含一个项目的HashSet<Obj>。尝试添加到集合中的新项目与现有项目.equals()相同。为了确认newElement实际上是相同的,我有一些调试打印循环通过我的HashSet并打印每个项目:

does current item .equals(newElement)

这证实了该集合中已存在.equals()对象。

这就是有趣的开始,如果我打电话给add(newElement)我希望它不会添加,或者至少覆盖已经在集合中的内容。该组在添加后应该只有1个唯一项。就我而言,它有2个!

为了弄清楚为什么add()正在以这种方式工作,我运行了一个本应该返回true的Set.contains(newElement),但在我的情况下它返回false。这就是为什么我的add()以它的方式工作的原因。

任何理由为什么一组中的项目可能是.equals(newElement)Set.contains(newElement)可能会返回错误?我检查了我的.equals(),它似乎按照我的预期工作,打印出来的对象显示.equals()确认的内容。我想也许是因为HashSet如何处理addcontains但是从Java文档中检查(o==null ? e==null : o.equals(e))

我也在重写hashCode(),我在打印中使用的值作为我的调试的一部分显示相同的逻辑项。

java hashset
2个回答
3
投票

集合中的项目可能是.equals(newElement)但Set.contains(newElement)可能返回false的任何原因?

是的 - 你需要实现hashCode()以及equals,它需要检查与equals()完全相同的字段。你说哈希码只是大致相等,这没有多大意义。如果hashCode()为两个不同的对象返回不同的结果(默认情况下,如果你没有覆盖它),那么HashSet将假设它们是唯一的(即使equals()返回true)。

如果hashCode()为两个对象返回相同的值,并且equals()返回true(在两个对象上对称),那么这将确保您不能在HashSet中同时拥有这两个对象。这个规则没有(明智的)例外,所以如果你认为hashCode()equals()都表现得正确且一致,那么你的逻辑必然存在缺陷。


0
投票

Equals和hashCode方法有一个特定的契约:

1.如果元素彼此相等,即equals返回true,则这些对象的hashCode值必须匹配。 2.如果对象的hashCode值相同,那么这并不意味着它们的等于将返回true,即。物体不必彼此相等,即碰撞是可能的。 现在分别考虑每个案例:

1.Equals和hashCode没有被重写,这意味着只有当链接相等时,equals才会返回true,并且hashCode可以相等或不相等。无论hashCode的值如何,大小都是2。 2.equals和hashCode被重新定义,然后我们将具有相同的哈希值,我们将得到相同的表格单元格,equals将确定列表中的对象已经存在,因此大小将等于1。 3.equals没有重新定义,hashCode被覆盖。在这种情况下,单元格索引将是相同的,但在列表中找不到相同的元素,因此大小将等于2。 4.equals被覆盖,hashCode未定义。这取决于如何在Object类中生成hashCode的值。如果值相同,则列表将相同,因此,表中的元素数将为1.如果不同,搜索将出现在不同的列表中,并且将找不到重复项,然后是大小将等于2。

类似地,执行remove,contains操作。 有关HashSet / contains的示例:

class Dog{
String color;

public Dog(String s){
    color = s;
}   

}

 public class SetAndHashCode {
    public static void main(String[] args) {
    HashSet<Dog> dogSet = new HashSet<Dog>();
    dogSet.add(new Dog("white"));
    dogSet.add(new Dog("white"));

    System.out.println("We have " + dogSet.size() + " white dogs!");

    if(dogSet.contains(new Dog("white"))){
        System.out.println("We have a white dog!");
    }else{
        System.out.println("No white dog!");
    }   
}

}

© www.soinside.com 2019 - 2024. All rights reserved.