meiryo
meiryo

Reputation: 11687

Pass by value trouble with java's list add method

ArrayList<ArrayList<String>> list1 = new ArrayList<ArrayList<String>>();
ArrayList<String> list2 = new ArrayList<String>();

list2.add("foo");
System.out.println(list2); //[foo]
list1.add(list2);
System.out.println(list1); //[[foo]]
list2.set(0, "bar");
System.out.println(list2); //[bar]
System.out.println(list1); //[[bar]]

The code above shows 2 lists. When I add list2 (containing foo) to list1 they both now contain foo. But when I modify list2 to bar, list1 will change as well. I've always thought the add method only gives a copy of list2 to list1 and what I do to list2 will not change for list1.

How can I make it that I add list2 to list1 but allow list2 to be freely modified in the future so list1 will not be affected again?

Upvotes: 0

Views: 2934

Answers (3)

Peter Lawrey
Peter Lawrey

Reputation: 533492

In Java references are passed by value, not the object referenced. This means that list2.add(list1); cannot alter the reference list1 but it takes a reference to the same object and if you change that it is visible.

The way you should write this is

List<List<String>> list1 = new ArrayList<List<String>>();
List<String> list2 = new ArrayList<String>();

list2.add("foo");
System.out.println(list2); //[foo]
list1.add(new ArrayList<String>(list2)); // take a copy of the list.
System.out.println(list1); //[[foo]]
list2.set(0, "bar");
System.out.println(list2); //[bar]
System.out.println(list1); //[[foo]]

or

list1.add(list2); 
list2 = new ArrayList<String>();
list2.add("bar");
System.out.println(list2); //[bar]
System.out.println(list1); //[[foo]]

My example above is simple but my actual problem is buried in nested loops and such.

List<List<String>> list1 = new ArrayList<List<String>>();

for(some loop) {
    List<String> list2 = new ArrayList<String>();
    // populate list2, can be smaller than the previous list2 !!
    list1.add(list2);
}

Upvotes: 6

rseidi
rseidi

Reputation: 88

You should clone every item and add to a new list.

Upvotes: 0

AlexErofeev
AlexErofeev

Reputation: 161

How about list1.add(list2.clone()); ? This will create a copy of list2 (allocate memory, clone contents etc) and put reference to it in list1.

Upvotes: 1

Related Questions