Fiddle Freak
Fiddle Freak

Reputation: 2041

Copy Two Dimensional ArrayList as new

So the issue I'm having is after copying the 2d arraylist, changing the element from one 2d arraylist affects the other 2d arraylist. I want them to be completely separate in memory.

First example shows how it works correctly with 1d arraylists...

import java.util.ArrayList;
public class QuickTest {

    public static void main(String[] args) {
        ArrayList<Integer> firstList = new ArrayList<>();
        ArrayList<Integer> secondList = new ArrayList<>();

        Integer counter = 2;
        for(int arrI = 0; arrI < 4; arrI++, counter+=2){
            firstList.add(counter);
        }

        secondList = new ArrayList<>(firstList);

        System.out.println("firstList.get(2) = " + firstList.get(2));
        System.out.println("secondList.get(2) = " + secondList.get(2));

        firstList.set(2, 7);

        System.out.println("firstList.get(2) = " + firstList.get(2));
        System.out.println("secondList.get(2) = " + secondList.get(2));
    }
}

Expected output:

enter image description here

Notice how the element from the first arraylist is changed but not the second arraylist element is not changed. This is good and what we want.

Now to try and copy the 2d arraylists...

import java.util.ArrayList;
public class QuickTest {

    public static void main(String[] args) {
        ArrayList<ArrayList<Integer>> firstTwoDimList = new ArrayList<>();
        ArrayList<ArrayList<Integer>> secondTwoDimList = new ArrayList<>();

        firstTwoDimList.add(new ArrayList<Integer>());
        firstTwoDimList.add(new ArrayList<Integer>());
        firstTwoDimList.add(new ArrayList<Integer>());

        Integer counter = 2;
        for(int arrI = 0; arrI < firstTwoDimList.size(); arrI++, counter+=2){
            firstTwoDimList.get(arrI).add(counter);
            counter+=2;
            firstTwoDimList.get(arrI).add(counter);
        }

        secondTwoDimList = new ArrayList<>(firstTwoDimList);

        System.out.println("firstTwoDimList.get(1).get(0) = " + firstTwoDimList.get(1).get(0));
        System.out.println("secondTwoDimList.get(1).get(0) = " + secondTwoDimList.get(1).get(0));

        firstTwoDimList.get(1).set(0, 7);

        System.out.println("firstTwoDimList.get(1).get(0) = " + firstTwoDimList.get(1).get(0));
        System.out.println("secondTwoDimList.get(1).get(0) = " + secondTwoDimList.get(1).get(0));
    }
}

Unexpected output:

enter image description here

Anyone have any idea what the reason for this is, and what the best solution would be?

Upvotes: 5

Views: 4285

Answers (4)

Muhammad Qasim
Muhammad Qasim

Reputation: 107

You should iterate through the size of the first dimension of the firstTwoDimArray and add new reference of each second dimension to the secondTwoDimArray. i.e.

for(int index = 0; index < firstTwoDimList.size(); index++) {
    secondTwoDimList.add(new ArrayList<Integer>(firstTwoDimList.get(index)));
}

Upvotes: 2

Sweeper
Sweeper

Reputation: 271625

This is what is happening in the 1D array list case, in terms of references:

enter image description here

This is what is happening in the 2D array list case:

enter image description here

This means that when you copy an array list using this:

new ArrayList<>(someOldArrayList)

the items themselves don't get copied, only a new array list object is created, referring to all the items in the old array list.

In the second case, you are only changing what array list 2's items are, but index 1 of first list and second list refers to the same array list 2.

To fix this, you need to copy the array lists inside first list and second list as well. One way to do this:

secondList = new ArrayList<>(firstList.stream().map(x -> new ArrayList<>(x)).collect(Collectors.toList()));

Upvotes: 5

Fiddle Freak
Fiddle Freak

Reputation: 2041

I guess I was looking for something like this...

import java.util.ArrayList;
public class QuickTest {
    public static ArrayList<ArrayList<Integer>> getTwoDimArrListCopy(ArrayList<ArrayList<Integer>> original){
        ArrayList<ArrayList<Integer>> copy = new ArrayList<>();

        for (ArrayList<Integer> arr: original){
            copy.add(new ArrayList<Integer>(arr));
        }

        return copy;
    }

    public static void main(String[] args) {
        ArrayList<ArrayList<Integer>> firstTwoDimList = new ArrayList<>();
        ArrayList<ArrayList<Integer>> secondTwoDimList = new ArrayList<>();

        firstTwoDimList.add(new ArrayList<Integer>());
        firstTwoDimList.add(new ArrayList<Integer>());
        firstTwoDimList.add(new ArrayList<Integer>());

        Integer counter = 2;
        for(int arrI = 0; arrI < firstTwoDimList.size(); arrI++, counter+=2){
            firstTwoDimList.get(arrI).add(counter);
            counter+=2;
            firstTwoDimList.get(arrI).add(counter);
        }

        secondTwoDimList = getTwoDimArrListCopy(firstTwoDimList);

        System.out.println("firstTwoDimList.get(1).get(0) = " + firstTwoDimList.get(1).get(0));
        System.out.println("secondTwoDimList.get(1).get(0) = " + secondTwoDimList.get(1).get(0));

        firstTwoDimList.get(1).set(0, 7);

        System.out.println("firstTwoDimList.get(1).get(0) = " + firstTwoDimList.get(1).get(0));
        System.out.println("secondTwoDimList.get(1).get(0) = " + secondTwoDimList.get(1).get(0));
    }
}

I was just hoping there was a built in library that would do that getTwoDimArrListCopy() function for me...

Upvotes: 0

Eugene S
Eugene S

Reputation: 6910

The difference between your first and second example is that in the second one you use get(). This get() returns a new variable, so you assign the integers to it and not to the original ArrayList.

If you want to assign a value:

firstTwoDimList.set(1, new ArrayList<Integer>(Arrays.asList(0, 7)));

Upvotes: 0

Related Questions