alex
alex

Reputation: 5684

Copy lists of objects with list members

How can i copy a ArrayList containing objects with ArrayList members. Also it might be possible, that the members of the objects in the list also containing again ArrayList members, and so on. So is there a generic way to copy list of objects regardless of their members?

Implementing the Clone Interface for all involved objects seems to be a bad idea, since I read that its broken.

I created a small SSCCE to exemplify my problem:

class Foobar {
    public List<String> listMember;
    public String       primitiveMember;

    public Foobar() {
        listMember = new ArrayList<String>(Arrays.asList("a", "b", "c"));
        primitiveMember = "testABC";
    }
}
// Create list of Foobar
List<Foobar> foobars = new ArrayList<Foobar>();
foobars.add(new Foobar());
// Copy list of Foobar
List<Foobar> foobarsCopy = new ArrayList<Foobar>();
foobarsCopy.add(null);
Collections.copy(foobarsCopy, foobars);
// Modify source list
foobars.get(0).listMember.add("-1-");
// Output of references
System.out.println("Sourcelist has size of: " + foobars.get(0).listMember.size());
System.out.println("Destinationlist has size of: " + foobarsCopy.get(0).listMember.size());
System.out.println("Function 'Collections.copy(...) does not copy list members of members?: " + (foobars.get(0).listMember.size() == foobarsCopy.get(0).listMember.size()) + " - References: " + foobars.get(0).listMember.hashCode() + " vs " + foobarsCopy.get(0).listMember.hashCode());

Upvotes: 1

Views: 71

Answers (1)

Steve Benett
Steve Benett

Reputation: 12933

You can use a copy constructor, if you don't want to use the cloneable interface. This way you get new Objects for each instance of the List elements, and a independent reference of the copied List. In short you will have a deep copy of the Foobar elements.

class Foobar {
    public List<String> listMember;
    public String       primitiveMember;

    public Foobar() {
        listMember = new ArrayList<String>(Arrays.asList("a", "b", "c"));
        primitiveMember = "testABC";
    }

    public Foobar(List<String> list, String primitive) {
        this.listMember = list;
        this.primitiveMember = primitive;
    }

    // Use a copy constructor instead of the Cloneable interface
    public Foobar(Foobar foobar) {
        this.primitiveMember = foobar.primitiveMember;
        this.listMember = new ArrayList<String>(foobar.listMember);
    }

    public static void main(String[] args) {
        // Create list of Foobar
        List<Foobar> foobars = new ArrayList<Foobar>();
        foobars.add(new Foobar());

        // Copy list of Foobar with the copy constructor
        List<Foobar> foobarsCopy = new ArrayList<Foobar>(foobars.size());
        for (Foobar f : foobars) {
            foobarsCopy.add(new Foobar(f));
        }

        // add a new Foobar instance (hashcode will be different now)
        foobarsCopy.add(new Foobar(new ArrayList<String>(Arrays.asList("d", "e", "f")), "foo"));

        // Modify source list (hashcode again will be different)
        foobars.get(0).listMember.add("-1-");

        // Output of references
        System.out.println("Sourcelist has size of: " + foobars.get(0).listMember.size());
        System.out.println("Destinationlist has size of: " + foobarsCopy.get(0).listMember.size());
        System.out.println("Function 'Collections.copy(...) does not copy list members of members?: "
                + (foobars.get(0).listMember.size() == foobarsCopy.get(0).listMember.size()) 
                + "\n - References: " + foobars.get(0).listMember.hashCode() 
                + " vs " + foobarsCopy.get(0).listMember.hashCode());

    }

}

Upvotes: 1

Related Questions