【问题标题】:Java HashSet is allowing dupes; problem with comparable?Java HashSet 允许欺骗;有可比性的问题?
【发布时间】:2010-06-02 20:28:22
【问题描述】:

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

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

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

谢谢,
IVR复仇者

【问题讨论】:

    标签: java set comparable


    【解决方案1】:

    我在这里搞砸了什么?

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

    【讨论】:

      【解决方案2】:

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

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

      【讨论】:

      • 没有等号是完全无效的。
      【解决方案3】:

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

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

      规则是:

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

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

      【讨论】:

        【解决方案4】:

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

        【讨论】:

          【解决方案5】:

          你的对象是Comparable,可能你也实现了equals(),但是HashSets处理对象哈希,很可能你还没有实现hashCode()(或者你的hashCode()没有实现'不为(a.equals(b) == true) 的两个对象返回相同的哈希值。

          【讨论】:

            【解决方案6】:

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

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

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

            希望对你有帮助

            【讨论】:

              【解决方案7】:

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

              【讨论】:

              • 只有在equals被覆盖时才需要覆盖hashCode(定义是equal已经改变)。反过来不一定正确。将 hashCode 更改为返回 1 并保留 equals 是完全合法的。
              【解决方案8】:

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

              解决方案:

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

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

              【讨论】:

              • 提供的链接非常有用,对于像我这样的 bininer 人来说非常有用。
              猜你喜欢
              • 1970-01-01
              • 2017-12-27
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2015-09-15
              • 1970-01-01
              • 2012-02-16
              • 1970-01-01
              相关资源
              最近更新 更多