如何保持1对1的关系一致

时间:2014-11-23 20:03:29

标签: java relationship consistency

请考虑Lecturer.java中的以下代码。 Lecture.java中的setter具有完全相同的形式。另请注意,感兴趣的属性为private

public void setLecture(Lecture lecture) {
    if (this.lecture == lecture) return;

    if (this.lecture != null) {
        this.lecture.setLecturer(null);
    }

    this.lecture = lecture;

    if (this.lecture != null) {
        this.lecture.setLecturer(this);
    }
}

尝试设置之前未null的{​​{1}}值时,会产生无限循环。

我无法相信这很难保持1:1的关系一致 - 但我无法弄清楚如何做到这一点。如何解决这个问题?

3 个答案:

答案 0 :(得分:0)

最后,这是您的解决方案:

public class A {
    private B b;

    public void setB(B b) {
        if(this.b != null) {
            this.b.unsetA();
        }
        this.b = b;
        if(b != null && b.getA() != this) {
            this.b.setA(this);
        }
    }

    public void unsetB() {
        this.b = null;
    }

    public B getB() {
        return b;
    }

}

public class B {
    private A a;

    public void setA(A a) {
        if(this.a != null) {
            this.a.unsetB();
        }
        this.a = a;
        if(a != null && a.getB() != this) {
            this.a.setB(this);
        }
    }

    public void unsetA() {
        this.a = null;
    }

    public A getA() {
        return a;
    }

}

我的测试班:

public class Test {

    public static void main(String ... args) {
        A a1 = new A();
        B b1 = new B();
        A a2 = new A();
        B b2 = new B();

        checkForZeroOrTwoRelations(a1, a2, b1, b2);
        a1.setB(b1);
        checkForZeroOrTwoRelations(a1, a2, b1, b2);     
        b1.setA(a2);
        checkForZeroOrTwoRelations(a1, a2, b1, b2);
        b2.setA(a2);
        checkForZeroOrTwoRelations(a1, a2, b1, b2);
        b2.setA(null);
        checkForZeroOrTwoRelations(a1, a2, b1, b2);
    }

    private static void checkForZeroOrTwoRelations(A a1, A a2, B b1, B b2) {
        int i = 0;
        if(a1.getB() != null) i++;
        if(a2.getB() != null) i++;
        if(b1.getA() != null) i++;
        if(b2.getA() != null) i++;
        if(i != 0 && i != 2) {
            throw new IllegalStateException();
        }
    }
}   

答案 1 :(得分:0)

您只需将object属性设置为 null 即可打破无限循环。但首先必须将先前的值存储到临时变量中。它会在第一个if语句处停止,其中null等于null

public void setLecture(Lecture lecture) {

    if (this.lecture == lecture) {
        return;
    }

    if (this.lecture != null) {

        Lecture pastLecture = this.lecture;
        this.lecture = null;

        pastLecture.setLecturer(null);

        pastLecture = null;

    }

    this.lecture = lecture;

    if (lecture != null) {
        lecture.setLecturer(this);
    }
}

Gist

答案 2 :(得分:0)

我将其作为一个不同的答案发布,实际上我认为,我的第一个答案是你正在寻找的。

至于我的建议,您可以创建一个双向地图(或者您可以使用Guava HashBiMap)来确保关系完整性。

Map<Lecturer, Lecture> lecturerMap = new HashMap();
Map<Lecture, Lecturer> lectureMap = new HashMap();

public void addRelation(Lecturer lecturer, Lecture lecture) {

    this.checkIntegrity(lecturerMap,lectureMap, lecturer, lecture);
    this.checkIntegrity(lectureMap, lecturerMap, lecture, lecturer);

    lecturerMap.put(lecturer, lecture);
    lectureMap.put(lecture, lecturer);
}

private <T,V> void checkIntegrity(Map<T,V> mapf, Map<V,T> maps, T t, V v) {
    if (mapf.containsKey(t)) {
        V value = mapf.get(t);

        if (maps.containsKey(value)) {
            maps.remove(value);
        }

        mapf.remove(t);
    }
}

肯定有更复杂的方法可以做,但这项工作也是如此。

Gist