【问题标题】:Java: Duplicate objects getting added to set?Java:重复的对象被添加到集合中?
【发布时间】:2013-05-03 23:31:32
【问题描述】:

如果我运行以下代码,则输出为 2,这意味着该集合包含 2 个元素。但是我认为该集合应该包含 1,因为这两个对象基于 hashcode() 值以及.equals() 方法是相等的。 我的理解似乎有些明显的错误?

package HELLO;

import java.util.HashSet;
import java.util.Set;

public class Test {

    public static void main(String[] args) throws Exception {
        Set<Alpha> s = new HashSet<Alpha>();
        Alpha a1 = new Alpha();
        Alpha a2 = new Alpha();
        s.add(a1);
        s.add(a2);
        System.out.println(s.size());
    }
}   

class Alpha {
    int a = 10;

    public int hashcode() {
        return a;
    }

    public boolean equals(Object obj) {
        return (obj instanceof Alpha && ((Alpha) obj).a == this.a);
    }

    public String toString() {
        return "Alpha : " + a;
    }
}

【问题讨论】:

    标签: java hash hashcode hashset


    【解决方案1】:

    您的 hashcode 方法不会覆盖 Object 类的 hashCode 方法,因此您的 equals 方法会违反合同,因为它与 hashCode 结果不一致,并且您可以拥有“相等”但具有不同哈希码的对象。

    请记住:在覆盖方法时,您应该始终使用 @Override 注释,因为这将帮助您捕获此错误和类似错误。

    @Override  // ** don't forget this annotation
    public int hashCode() { // *** note capitalization of the "C"
      return a;
    }
    

    此外,您还需要改进代码格式,尤其是在此处发布代码供我们审核时。如果它符合标准,我们将能够更好地理解您的代码并为您提供帮助(这就是存在标准的原因)。所以尽量保持你的缩进与同一块中的所有代码行在同一级别缩进一致,并且你需要确保基本级别的代码,包括导入、外部类声明和它的结束大括号,是齐平的:

    import java.util.HashSet;
    import java.util.Set;
    
    public class Test {
    
       public static void main(String[] args) throws Exception {
          Set<Alpha> s = new HashSet<Alpha>();
          Alpha a1 = new Alpha();
          Alpha a2 = new Alpha();
          s.add(a1);
          s.add(a2);
          System.out.println(s.size());
       }
    }
    
    class Alpha {
       int a = 10;
    
       @Override
       public int hashCode() {
          return a;
       }
    
       public String toString() {
          return "Alpha : " + a;
       }
    
       @Override
       public boolean equals(Object obj) {
          if (this == obj)
             return true;
          if (obj == null)
             return false;
          if (getClass() != obj.getClass())
             return false;
          Alpha other = (Alpha) obj;
          if (a != other.a)
             return false;
          return true;
       }
    }
    

    关于这方面的精彩评论,请阅读:Overriding equals and hashCode in Java

    【讨论】:

    • 谢谢!永远不会忘记使用@Override :)
    • @snow_leopard:这是一个很好的习惯。祝你好运!
    • 除了“@Override”之外,我还必须在 equals 函数中添加一行,否则该集合无法检测到重复项并始终包含多次具有相同内容的对象: if(this. hashCode() == msg.hashCode()) return true;
    • @sven:我实际上强烈建议不要使用您的代码行,因为它与 equals 和 hashCode 合同的规定完全相反。您对该行的需求表明您的 equals 方法可能存在其他问题。
    • @hoverkraft:你是对的,我在 equals() 中有一个错误,它在错误的情况下返回 false。所以出现了多个条目。在 equals() 中检查哈希是个坏主意。
    【解决方案2】:

    @Overrides注解是重写超类中的同名方法。

    @Override
    public int hashCode() {
        return a;
    }
    
    @Override
    public boolean equals(Object obj) {
        return (obj instanceof Alpha && ((Alpha) obj).a == this.a);
    
    }
    
    @Override
    public String toString() {
        return "Alpha : " + a;
    }
    

    【讨论】:

      【解决方案3】:

      您的方法 hashcode 应命名为 hashCode(大写字母“C”)。

      如果您计划覆盖方法,则应使用 @Override 注释。

      如果您使用了该注释,您会更早注意到问题,因为代码不会编译。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-01-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-02-19
        • 2014-12-09
        • 1970-01-01
        相关资源
        最近更新 更多