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

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

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

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

谢谢,
IVR复仇者

我搞砸了什么,这里?

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

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

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

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

你的调试器没有打破compareTo()因为它从未与HashSet

规则是:

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

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

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

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

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

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

如果你通过写一个Song aSong而不是Object aSong你的equals方法永远不会被调用。

希望这可以帮助

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

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

解:

重写hashCode()equals()方法,并根据类的属性应用逻辑。 一定要读取equals和hashcode合约

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