【问题标题】:Is it bad practice to equal() class instances by just their unique instanceID?仅通过其唯一的 instanceID 来 equal() 类实例是不好的做法吗?
【发布时间】:2015-03-17 17:40:55
【问题描述】:

我有一个类,它在实例化时为其对象创建一个唯一 ID,如下所示:

public class Foo {

    private final static AtomicInteger UNIQUE_ID = new AtomicInteger(0);
    private final int id;
    private final String name;         
    private final int hashcode;
    public Foo(String name) {
         id = UNIQUE_ID.GetAndIncrement();
         this.name = name;
         int result = 17;
         int result = 31 * result + id;
         int result = 31 * result + name.hashCode();
         hashcode = result;
    }
    public int getInstanceID() { return id; }

现在我想以这种方式实现 hashCode 和 equals:

    public boolean equals(Object obj) {

        if (obj == this)
            return true;
        if (!(obj instanceof Foo))
            return false;

        Foo other = (Foo) obj;
        return other.getInstanceID == getInstanceID();
    }

    public int hashCode() { return hashcode; }
}

如果我只比较对象的 ID 而不考虑任何其他可能与一个 Foo 不同的字段,这是否被认为是不好的做法?另外,我应该仍然关注 hashcode 函数中的每个字段还是只使用 id?

【问题讨论】:

    标签: java equals uniqueidentifier identifier


    【解决方案1】:

    嗯。合同是这样的 - 如果两个对象相等,它们必须具有相同的hashCode。你还没有覆盖hashCode(),所以你可以有2个具有不同哈希码的相等对象,这是错误的。覆盖hashcode() 以遵守合同,那么它可能就可以了。

    【讨论】:

    • 是的,我知道 hashCode() 合约,我当然实现了它。所以如果我实现它,我的哈希码函数应该仍然使用所有字段吗?整数结果 = 17;结果 = 31 * 结果 + id;结果 = 31 * 结果 + name.hashCode();
    • @Jan - 这就是问题所在。您的 hashCode() 应遵循 equals() 即,合同未指定应包含所有字段的内容。 return 5 是一个有效的 hashCode() 实现。唯一重要的是对于任何两个实例x 和y 如果x.equals(y) 为真,那么x 和y 应该具有相同的hashCode
    • 好的,所以我可以轻松地返回带有 hashCode 函数的 instanceID 并且非常好,因为我知道每个类 ID 都是唯一的?或者如果可能,hashCodes 是否应该是全局唯一的?
    • @Jan - 不。它们不必是全球唯一的。它们应该是一致的。例如s1=new String("abc") 和s2 = new String("abc") 是两个不同的 实例,它们是equal。因此 2 个实例的 hashCodes 将相同。
    • 所以,一旦我知道,两个对象实例永远不应该被认为是相等的,我可以像这样实现相等:return obj == this 和 hashCode 也可以保持默认方式,因为它可能使用实例的唯一性?
    【解决方案2】:

    最佳实践是以这样的方式实现 hashCode 函数,以便它均匀地分布集合(哈希表)中的对象。产生相同 hashCode 的对象进入同一个桶。 hashCode函数的作用是识别桶。

    如果您有一个错误的函数为所有返回相同的值,那么想象这些对象都存储在一个存储桶中。这使得集合的工作变得困难,因为它必须遍历每个对象并在它们上运行 equals 方法,直到找到合适的对象(如果可用)。

    如果你有一个好的 hashCode 函数,那么不同的对象就会被不同的桶识别。因此,给定存储桶中的对象更少,这意味着需要更少的搜索。

    最好使用对象的属性来唯一标识它。

    【讨论】:

      猜你喜欢
      • 2021-03-23
      • 1970-01-01
      • 2018-01-20
      • 1970-01-01
      • 2011-05-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多