HashSet项目等于,但HashSet不包含

时间:2017-12-20 14:57:59

标签: java hashset

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

does current item .equals(newElement)

这确认集合中已有.equals()个对象。

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

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

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

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

2 个答案:

答案 0 :(得分:3)

  

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

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

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

答案 1 :(得分: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!");
    }   
}

}