Reputation: 23
I wanted to add some random values to a two-dimensional ArrayList by creating a one dimensional array with some randomly generated values, adding it to the main array then clearing the one dimensional array and repeating this proccess a few times.
Here's what I wrote:
ArrayList<ArrayList<Integer>> a = new ArrayList<>();
ArrayList<Integer> b = new ArrayList<>();
for(int i=0;i<5;i++) {
b.add(r.nextInt(10));
b.add(r.nextInt(10));
System.out.println("B - "+b);
a.add(b);
b.clear();
}
System.out.println(a);
This is my output:
B - [4, 4]
B - [3, 7]
B - [3, 7]
B - [0, 1]
A - [[], [], [], [], []]
[]
Could someone please fix this and explain why this occurs?
Upvotes: 0
Views: 45
Reputation: 102902
When you write:
ArrayList<Integer> b = new ArrayList<>();
That's saying: Make an object (treasure chest) of type ArrayList and make it on the heap (bury it in the sand), because all objects are made there (all objects are buried in the sand, that's just how java works). This object does not now or ever have names (objects (treasure chests) do not have names).
Then, make a new reference (paper that can hold a treasure map). Set the value of the reference to point at the newly created object (draw a map to location you just buried the freshly created treasure in the sand). We shall call this reference (treasure map) b
(in java, variables have names, and variables of non-primitive types are treasure maps. In that way, whilst treasure cant have a name, maps can).
Then, you do:
b.add(r.nextInt(10));
The .
between b
and add
is java-ese for: "Take the reference 'b', follow it, and invoke the 'add' object on the object you found there" (Take the treasure map we called b
, follow it, and dig. Open the box, run the add job on what you found). You should get into your head that .
is java for follow the map and dig.
Then you run:
a.add(b);
and this is the crucial part: a
is a list of treasure maps. You seem to be under the impression that a is a list of treasures. That's not possible in java, all non-primitives are references, that is, all non-primitive things are done in terms of treasure maps, never treasures.
So, in terms of treasure, this is what this algorithm does:
a
.b
.b
map, follow it, open the box, roll a die, put the die in the box.b
treasure map and make it a copy of it. Follow the a
map to find the treasure-map-holding treasure chest, and put the copy of the b map in it.b
map, follow it, open the box, find the dice, toss em out.So, you end up with only 2 treasure chests, total: One with 5 copies of the exact same map, all a map to find the other chest you made, and then one other chest that you put a bunch of dice into and then tossed em back out again, ending in a state where it is empty.
You then print this all, which naturally confirms all of the above: A list with 5 empty lists.
What you actually want is to create a new treasure chest every time, and not clear the old one. So, take:
b.clear();
and replace that with:
b = new ArrayList<Integer>();
i.e, instead of: "Follow this treasure map, find the chest, open it, remove all the dice", you go with: "Make an entirely new treasure chest, bury it in the sand, take my treasure map called b
, erase it, and draw the map to newly created chest I just buried. Leave the old chest in piece, with the dice in, don't touch that".
Upvotes: 1
Reputation: 367
You should try re-initializing the array b instead of clearing it.
Upvotes: 1