My problem is that when I call my restore() method, it gives me the original list which was initialized in the Snapshot constructor. I don't want its affecting by all changes. What must I change in Snapshot class?
import java.util.ArrayList;
public class Snapshot {
private ArrayList<Integer> data;
public Snapshot(ArrayList<Integer> data) {
this.data = data;
}
public ArrayList<Integer> restore() {
return this.data;
}
public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
Snapshot snap = new Snapshot(list);
list.set(0, 3);
list = snap.restore();
System.out.println(list); //it shoul lod "[1,2]"
list.add(4);
list = snap.restore();
System.out.println(list);//it shoul lod "[1,2]"
}
}
CodePudding user response:
Well, an ArrayList
is a mutable collection, which means it can be modified. With this.data = data
, you copy the reference, so now you have two strings attached to the same balloon.
You could just create a defensive copy to just avoid this:
class Snapshot {
private List<Integer> list;
Snapshot(List<Integer> list) {
this.list = new ArrayList<>(list);
}
}
There exists an ArrayList
constructor which accepts another list as argument, in order to copy the list. This is called a copy constructor.
CodePudding user response:
Currently
public ArrayList<Integer> restore() {
return this.data;
}
this works as a getter, it returns reference to the data
variable.
Also inside your constructor you are passing a reference to array and assigning it to your variable data
. Now the data
points to the ArrayList
passed through the constructor. Any changes to this array list within Snapshot instances will be also visible to whichever class is passing ArrayList<Integer> data
to the constructor. That's how Java works.
If you want to have a way to reset the data
variable to be the same clone of the one passed through the constructor, you need to make a clone, operate on it, and keep the initial reference, so that the restore method can make a new copy based on that reference.
May be something like this will work:
public class Snapshot {
private ArrayList<Integer> dataReference;
private ArrayList<Integer> dataClone;
public Snapshot(ArrayList<Integer> data) {
this.dataReference= data;
this.dataClone = new ArrayList<>(data);
}
public ArrayList<Integer> restore() {
return this.dataClone = new ArrayList<>(dataReference);
}
I'm a bit rusty with Java but try it out. You can look out for further reading on this topic like here or find similar https://howtodoinjava.com/java/collections/arraylist/arraylist-clone-deep-copy/