Java HashSet允许欺骗;问题可比吗?

时间:2010-06-02 20:28:22

标签: java set comparable

我有一个类“Accumulator”,它实现了Comparable compareTo方法,我试图将这些对象放入HashSet。

当我向HashSet添加()时,我在调试器中的compareTo方法中看不到任何活动,无论我在哪里设置断点。另外,当我完成add()时,我在Set中看到了几个重复项。

我搞砸了什么,这里;为什么不比较,因此允许欺骗?

谢谢,
IVR Avenger

8 个答案:

答案 0 :(得分:17)

  

我搞砸了什么,这里?

HashSet基于hashCode(),而不是基于compareTo()。您可能会将其与TreeSet混淆。在这两种情况下,请务必以与其他方法一致的方式实现equals()

答案 1 :(得分:11)

您需要正确实施hashCode()equals()

您必须覆盖hashCode并根据类中的值返回一个数字,以便任何两个相等的对象具有相同的哈希码。

答案 2 :(得分:6)

HashSet使用hashCode()equals()方法来防止添加重复项。首先,它获取要添加的对象的哈希码。然后,它找到该哈希码的相应存储桶,并使用equals()方法迭代该存储桶中的每个对象,以查看该集中是否已存在任何相同的对象。

您的调试器未在compareTo()上中断,因为它从未与HashSet一起使用!

规则是:

  1. 如果两个对象相等,那么它们的哈希码 必须相等。

  2. 但是如果有两个对象的哈希码 是相等的,那么意味着 对象是平等的!它可能是 这两个对象碰巧有相同的哈希值。

答案 3 :(得分:2)

当hashCode为2个对象返回不同的值时,则不使用equal。顺便说一句,compareTo与散列集合没有任何关系:)但是排序集合

答案 4 :(得分:2)

您的对象是Comparable,可能您已经实现了equals(),但是HashSets处理了对象哈希值,并且您没有实现hashCode()的可能性(或者hashCode()的实现不会为(a.equals(b) == true)的两个对象返回相同的哈希值。

答案 5 :(得分:2)

人们往往会忽略一件导致巨大错误的事情。 定义equals方法时,始终将参数作为对象类,然后将对象转换为所需的类。 例如

   public bolean equals(Object aSong){
     if(!(aSoneg instanceof Song)){
       return false;
     }
     Song s=(Song) aSong;
     return getTitle().equals(s.getTitle());
   }

如果你通过写歌歌曲而不是对象aSong你的等号方法永远不会被调用。

希望这有帮助

答案 6 :(得分:1)

HashSet使用hashCode和equals。 TreeSet使用Comparable接口。注意:如果您决定覆盖hashcode或equals,则应始终覆盖另一个。

答案 7 :(得分:1)

当您创建类累加器的对象时,它会占用 JVM 中的新空间,并在每次添加对象时返回唯一的 hashCode HashSet的即可。它不依赖于对象的值,因为您没有覆盖 hashCode()方法,因此它将调用 Object hashCode()方法这将为您的程序中创建的每个对象返回唯一的hashCode。

解决方案:

覆盖 hashCode() equals()方法,并根据类的属性应用逻辑。请务必阅读equals和hashcode合约

http://www.ibm.com/developerworks/java/library/j-jtp05273/index.html