English 中文(简体)
执行平等与洗衣 Java有通告的物体的代码
原标题:Implementing equals and hashCode for objects with circular references in Java

我有两门课,这两门都提到其他物体。 它们认为类似(简化了这一规定;在我的实际领域模式A类中,有B类清单,每个B类参照的是A类:

public class A {

    public B b;
    public String bKey;

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((b == null) ? 0 : b.hashCode());
        result = prime * result + ((bKey == null) ? 0 : bKey.hashCode());
        return result;
    }
    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (!(obj instanceof A))
            return false;
        A other = (A) obj;
        if (b == null) {
            if (other.b != null)
                return false;
        } else if (!b.equals(other.b))
            return false;
        if (bKey == null) {
            if (other.bKey != null)
                return false;
        } else if (!bKey.equals(other.bKey))
            return false;
        return true;
    }
}

public class B {

    public A a;
    public String aKey;

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((a == null) ? 0 : a.hashCode());
        result = prime * result + ((aKey == null) ? 0 : aKey.hashCode());
        return result;
    }
    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (!(obj instanceof B))
            return false;
        B other = (B) obj;
        if (a == null) {
            if (other.a != null)
                return false;
        } else if (!a.equals(other.a))
            return false;
        if (aKey == null) {
            if (other.aKey != null)
                return false;
        } else if (!aKey.equals(other.aKey))
            return false;
        return true;
    }
}

The hashCode and qualitys have been produced by Eclipse using both areas of A and B. 问题是,在<条码>中,对任一物体均采用<条码>。 由于两者都称作其他物体的<代码>等于和hashCode方法。 例如,以下方案将失败<代码>StackOverflowError。 根据上述目标:

    public static void main(String[] args) {

        A a = new A();
        B b = new B();
        a.b = b;
        b.a = a;

        A a1 = new A();
        B b1 = new B();
        a1.b = b1;
        b1.a = a1;

        System.out.println(a.equals(a1));
    }

如果以这种方式界定与循环关系相关的领域模式存在固有的错误,请让我知道。 只要我能说这是一个相当常见的情况,那是正确的?

界定<代码>hashCode和此处平等的最佳做法是什么? 我想在<代码>上保留所有领域。 这种方法能够真正地对目标进行深刻的平等比较,但我看不出我如何处理这个问题。 感谢!

最佳回答

我同意I82Much的意见,即你应避免把自己的母子带上布局:信息重复通常只会导致麻烦,但你可能需要这样做。

Even if you leave the parent reference in B, as far as hash codes are concerned you should completely ignore the parent reference and only use the true inner variables of B to build the hash code.

The As are just containers and their value is fully determined by their content, which is the values of the contained Bs, and so should their hash keys.

If A is an unordered set, you must be very careful that the hash code you are building from the B values (or B hash codes) is not dependent on some ordering. For example, if the hash code is build by adding and multiplying the hash codes of the contained B s in some sequence, you should first order the hash codes by increasing order before computing the result of the sums/multiplications. Similarly, A.equals(o) must not depend on the ordering of the Bs (if unordered set).

请注意,如果您在<代码>A内使用<>java.util.Collection,则仅贴上 Bs hash Code by regarding the parent reference will natural given effective A hashcode since the Collections have wellh Code byault (ordering or not).

问题回答

在典型模式中,大多数实体都有独特的身份识别。 该数据库在各种使用案例(特别是数据库的检索/浏览)中很有用。 国际不动产业联合会(国际不动产业联合会)是这样一个独特的工地。 因此,比较这些实体的共同做法是比较它们的识别资料:

@Override
public boolean equals(Object obj) {
    if (obj == null)
        return false;
    if (!getClass().equals(obj.getClass()))
        return false;
    return this.bKey.equals(((B) obj).bKey);
}


@Override
public int hashCode() { return bKey.hashCode(); }

您可以问:“如果两个B物体有相同的识别资料,但情况不同(其田地价值不同)。” 你的法典应当确保此类事情不会发生。 无论你如何执行<条码>等值,还是<条码>,这都是一个问题,因为它基本上意味着你在你的系统中拥有两种不同的实体,而你获得的就是能够说明正确的实体。

You could have two flavors of equals -- the override of Object.equals and one that s better suited for recursion. The recursive equality check takes an A or B -- whichever is the other class of this one -- which is the object you re calling the recursive equality on behalf of. If you re calling it on behalf of this.equals, you pass in null. For instance:

A {
    ...
    @Override
    public boolean equals(Object obj) {
        // check for this, null, instanceof...
        A other = (A) obj;
        return recursiveEquality(other, null);
    }

    // package-private, optionally-recursive equality
    boolean recursiveEquality(A other, B onBehalfOf) {
        if (onBehalfOf != null) {
            assert b != onBehalfOf;
            // we got here from within a B.equals(..) call, so we just need
            // to check that our B is the same as the one that called us.
        }
        // At this point, we got called from A.equals(Object). So,
        // need to recurse.
        else if (b == null) {
            if (other.b != null)
                return false;
        }
        // B has a similar structure. Call its recursive-aware equality,
        // passing in this for the onBehalfOf
        else if (!b.recursiveEquality(other.b, this))
            return false;

        // check bkey and return
    }
}

因此,A. Equals:

  1. A.equals calls `recursiveEquality(otherA, null)
    1. if this.b != null, we end up in the third if-else block, which calls b.recursiveEquality(other.b, this)
      1. in B.recursiveEquality, we hit the first if-else block, which simply asserts that our A is the same one that was passed to us (ie, that the circular reference isn t broken)
      2. we finish B.recursiveEquality by checking aKey (depending on your invariants, you may want to assert something based on what happened in step 3). B.recursiveEquality returns
    2. we finish A.recursiveEquality by checking bKey, possibly with similar asserts
  2. A.equals returns the result of the recursive equality check




相关问题
Spring Properties File

Hi have this j2ee web application developed using spring framework. I have a problem with rendering mnessages in nihongo characters from the properties file. I tried converting the file to ascii using ...

Logging a global ID in multiple components

I have a system which contains multiple applications connected together using JMS and Spring Integration. Messages get sent along a chain of applications. [App A] -> [App B] -> [App C] We set a ...

Java Library Size

If I m given two Java Libraries in Jar format, 1 having no bells and whistles, and the other having lots of them that will mostly go unused.... my question is: How will the larger, mostly unused ...

How to get the Array Class for a given Class in Java?

I have a Class variable that holds a certain type and I need to get a variable that holds the corresponding array class. The best I could come up with is this: Class arrayOfFooClass = java.lang....

SQLite , Derby vs file system

I m working on a Java desktop application that reads and writes from/to different files. I think a better solution would be to replace the file system by a SQLite database. How hard is it to migrate ...

热门标签