Java ArrayList of ArrayList
This is what you have now
ArrayList<ArrayList<Integer>> outer = new ArrayList<ArrayList<Integer>>();
ArrayList<Integer> inner = new ArrayList<Integer>();
will create
outer -> []
inner -> []
After
inner.add(100);
inner.add(200);
your situation looks like
outer -> []
inner -> [100, 200]
Here comes confusing part
outer.add(inner);
outer.add(inner);
which in fact copy value of inner
reference which means they point to same list from inner
outer -> [ reference1 , reference2 ]
| |
+-------+ |
+---------------------+
↓
inner +-> [100, 200]
which means that if you change state of list held by inner
you will be able to see these changes using reference1
and reference2
. Same if you change this list via other references, so when you use
outer.get(0).add(300);
get(0)
returns list which you can access also via inner
or get(1)
and adding new element so now situation looks like
outer -> [ reference1 , reference2 ]
| |
+-------+ |
+---------------------+
↓
inner -> [100, 200, 300]
That is why when you print outer
you are seeing
[[100, 200, 300], [100, 200, 300]].
^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^
from get(0) from get(1)
What you actually need is to create separate list so reference1
and reference2
will point to two separate lists. So you need something like
outer -> []
inner1 -> [100, 200]
inner2 -> [100, 200]
which will be later organized to
outer -> [ reference1 , reference2 ]
| |
+------+ |
↓ |
inner1 -> [100, 200] |
|
+--------------------+
↓
inner2 -> [100, 200]
You can do it this way
List<List<Integer>> outer = new ArrayList<List<Integer>>();
List<Integer> inner1 = new ArrayList<Integer>();
List<Integer> inner2 = new ArrayList<Integer>();
inner1.add(100);
inner1.add(200);
inner2.add(100);
inner2.add(200);
outer.add(inner1);
outer.add(inner2);
outer.get(0).add(300);
System.out.println(outer);
You are adding a reference to the same inner ArrayList
twice to the outer list. Therefore, when you are changing the inner list (by adding 300), you see it in "both" inner lists (when actually there's just one inner list for which two references are stored in the outer list).
To get your desired result, you should create a new inner list :
public static void main(String[] args) {
ArrayList<ArrayList<Integer>> outer = new ArrayList<ArrayList<Integer>>();
ArrayList<Integer> inner = new ArrayList<Integer>();
inner.add(100);
inner.add(200);
outer.add(inner); // add first list
inner = new ArrayList<Integer>(inner); // create a new inner list that has the same content as
// the original inner list
outer.add(inner); // add second list
outer.get(0).add(300); // changes only the first inner list
System.out.println(outer);
}
The command outer.add(inner)
adds a reference to inner
, not a copy of it.
So, when you add two references to inner
to the ArrayList outer
, you're adding two of the same thing. Modifying inner
through outer.get(0)
also modifies the value in outer.get(1)
, because they refer to the same thing.
If you create a copy of inner
and use that instead, then you'll have two different instances and be able to modify them separately. You can do this with a simple command:
outer.add(new ArrayList<[var type]>(inner));
The instruction for new ArrayList(inner)
creates a new ArrayList
with the contents of inner
inside of it - but doesn't use the same instance as inner
. Thus, you'll retain the content, but not retain the duplicated reference.
By adding the new copy instead of the reference, you can modify the copy without modifying what you might call the "original."