Java list changed when update another one

Viewed 2989

Supposing we have:

public class Test {

    private List<String> mWorkList;
    private List<String> mOriginalList;

    public Test(List<String> list) {
        mWorkList = list;
        mOriginalList = list;
    }

    public void updateData(List<String> newList) {
        mWorkList.clear();
        mWorkList.addAll(newList);
    }
}

I want to change only mWorkList but mOriginalList is changed too when I call updateData(List<String>). So how should I do it to keep mOriginalList as initially assigned in constructor?

5 Answers

In Java you pass variables by their reference. This means that whenever you do an assignment like mWorkList = list the variable mWorkList will point to the same place in memory where list is currently pointing. If you do mOriginalList = list, then mOriginalList will also point to that position. I.e. all three lists refer the same object at that point.


If you want independent lists you need to copy all values from the list to a new list like this:

List<String> myList = new ArrayList<>(otherList);

This constructor of ArrayList automatically adds all values from the other list, here is its documentation.


Your code could then look like:

public Test(List<String> list) {
    mWorkList = new ArrayList<>(list);
    mOriginalList = new ArrayList<>(list);
}

Or if you don't intent to change mOriginalList you could also leave it as mOriginalList = list. But then bear in mind that if the user makes changes to list (which comes from outside of your class) they will also be reflected in your mOriginalList which could easily lead to nasty bugs.

You should create new List object in function Test, because all your lists refer to one variable

public Test(List<String> list) {
    mWorkList = new ArrayList<>(list);
    mOriginalList = new ArrayList<>(list);
}

You are setting both list with the same instance reference with

mWorkList = list;
mOriginalList = list;

You need to create a new instance for mOriginalList by duplicating the list. This can be done with one of the constructor of ArrayList(Collection).

mOriginalList = new ArrayList<>(list);

Please note that the instances in both list are the same, so if you update an instance in list, it will be changed in mOriginalList. If you want to break that link too, you will need to clone the list and his content.

Whenever you assign a object to another object only the reference is assigned (Shallow copy). You should call copy constructor to make a deep copy.

public class Test {

    private List<String> mWorkList;
    private List<String> mOriginalList;


    public Test(List<String> list) {
        mWorkList = new ArrayList<>(list);
        mOriginalList = new ArrayList<>(list);
    }

    public void updateData(List<String> newList) {
        mWorkList.clear();
        mWorkList.addAll(newList);
    }
}                  

In java every variable is a reference, so in this case it's normal that both variable changes if you change one of them.

To keep a copy you have to create a new object and clone the original one.

Related