简体   繁体   中英

Java 8 - Get the 'parent' object of a list element

I have the following Code:

public class A {
   private String name;
   private List<B> bs;

   public A(String name) {
       this.name = name;
       this.bs = new ArrayList<>();
   }

   public void addB(B b) {
       bs.add(b);
   }
   public List<B> getBs() {
       return bs;
   }    
}

public class B {
    private String name;

    public B(String name) {
        this.name = name;
    }

    public String toString() {
        return name;
    }   
}

And the following Main:

public static void main(String[] args) {
        A a1 = new A("A1");
        A a2 = new A("A2");

        B b1 = new B("B1");
        B b2 = new B("B2");
        B b3 = new B("B3");

        a1.addB(b1);
        a2.addB(b2);
        a1.addB(b3);

        System.out.println(a1.getBs()); // [B1, B3]

        b3.getA(); // How can I do this? => Should return A1

}

Now I need to get all the B's of an given A . Which works perfectly.

But I also need to get the A of a given B .

Every B is unique. So each B can only be a member of one A .

What is the best way to do this?

You can add A member to B

public class B {
    private String name;
    private A a;

    public B(String name) {
        this.name = name;
    }

    public String toString() {
        return name;
    }

    public void setA(A a) {
        this.a = a;
    }

    public A getA() {
        return this.a;
    }
}

And set it when adding B to A

public void addB(B b) {
    bs.add(b);
    b.setA(this);
}

To get the A from a B you need a reference to A somewhere.

  • each B can have a reference to the A
  • you can have a collection of all the A s and search them to find which contains the B

One way to achieve what you are looking for is to set the A in the constructor of B This ensures there is exactly one A it is a member of

class A {
    private final String name;
    private final List<B> bs = new ArrayList<>();

    public A(String name) {
        this.name = name;
    }

    public B addB(String name) {
        bs.add(new B(this, name));
    }
}

class B {
    final A parent;
    final String name;

    B(A parent, String name) {
        this.parent = parent;
        this.name = name;
    }

    public A getA() { return parent; }

This way a B can only be added to one A and B knows which one.

public static void main(String[] args) {
    A a1 = new A("A1");
    A a2 = new A("A2");

    B b1 = a1.addB("B1");
    B b2 = a2.addB("B2");
    B b3 = a2.addB("B3");

    System.out.println(a1.getBs()); // [B1, B3]

    assert a2 == b3.getA();

When you add a B to an A's List, you have to also tell the B what its A parent reference is.

class A {
    private List<B> children;

    public void addChild(B b) {
        if (b != null) {
            this.children.add(b);
            b.setParent(this);
        }
    }
}

class B {
    private A parent;

    public void setParent(A a) {
        if (a != null) {
            this.parent = a;
        }
    }
}

Watch out for circular reference and out of memory errors. You create a B, which a reference to an A, which has a List of Bs, etc.

As @PeterLawrey said, this is what I would do:

public class A {
   private String name;
   private List<B> bs;

   public A(String name) {
       this.name = name;
       this.bs = new ArrayList<>();
   }

   public void addB(B b) {
       bs.add(b, this);
   }
   public List<B> getBs() {
       return bs;
   }    
}

public class B {
    private String name;
    private A referenceToA;

    public B(String name, A referenceToA) {
        this.name = name;
        this.referenceToA = referenceToA;
    }

    public String toString() {
        return name;
    }

    public A getReferenceToA()
    {
        return referenceToA;
    }
}

b3 has no idea (and it shouldnt, because of circular references) about which collection is holding it.

you have to instead do it the opposite: find if a1, a2 or a3 has b3

Use an inner class and keep the instances immutable so that you don't risk having inconsistencies:

class A {

    private final String name;
    private final List<B> bs;

    public A(String name) {
        this.name = name;
        bs = new ArrayList<>();
    }

    public B addB(String name) {
        B b = new B(name);
        bs.add(b);
        return b;
    }

    public List<B> getBs() {
        return Collections.unmodifiableList(bs);
    }


    class B {

        private final String name;

        public B(String name) {
            this.name = name;
        }

        public A getA() {
            return A.this;
        }

    }

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM