How to Clone Arraylist and Also Clone Its Contents

clone(): ArrayList.clone() I thought does a shallow copy

Shallow copy does not mean that they point to the same memory location. That would be just an assignment:List b = a;.

Cloning creates a new instance, holding the same elements. This means you have 2 different lists, but their contents are the same. If you change the state of an object inside the first list, it will change in the second list. (Since you are using an immutable type - Integer - you can't observe this)

However, you should consider not using clone(). It works fine with collections, but generally it's considered broken. Use the copy-constructors - new ArrayList(originalList)

How to clone ArrayList and also clone its contents?

You will need to iterate on the items, and clone them one by one, putting the clones in your result array as you go.

public static List<Dog> cloneList(List<Dog> list) {
List<Dog> clone = new ArrayList<Dog>(list.size());
for (Dog item : list) clone.add(item.clone());
return clone;
}

For that to work, obviously, you will have to get your Dog class to implement the Cloneable interface and override the clone() method.

How to copy an ArrayList that cannot be influenced by the original ArrayList changes?

clone() for ArrayLists should be avoided because even if it creates a new List instance, it holds the same elements. So an element changed on the first List will also be changed on the second one. Two different objects holding the same references.

The code below will create a new instance with new elements.

ArrayList<Object> realClone = new ArrayList<Object>();
for(Object o : originalList)
realClone.add(o.clone());

How to deep copy a ListObject

You need to implement a correct clone() method like

public class Student implements Cloneable {
public int id;
public String name;
public List<Integer> score;
public Address address;

......

@Override
protected Object clone() throws CloneNotSupportedException {
Student std = new Student();
std.id = this.id; // Immutable
std.name = this.name; // Immutable
std.score = this.score.stream().collect(Collectors.toList()); // Integer is immutable
std.address = (Adress) this.address.clone();
return std;
}

How to make a separated copy of an ArrayList?

Yes that's correct - You need to implement clone() (or another suitable mechanism for copying your object, as clone() is considered "broken" by many programmers). Your clone() method should perform a deep copy of all mutable fields within your object. That way, modifications to the cloned object will not affect the original.

In your example code you're creating a second ArrayList and populating it with references to the same objects, which is why changes to the object are visible from both Lists. With the clone approach your code would look like:

List<Foo> originalList = ...;

// Create new List with same capacity as original (for efficiency).
List<Foo> copy = new ArrayList<Foo>(originalList.size());

for (Foo foo: originalList) {
copy.add((Foo)foo.clone());
}

EDIT: To clarify, the above code is performing a deep copy of the original List whereby the new List contains references to copies of the original objects. This contrasts to calling ArrayList.clone(), which performs a shallow copy of the List. In this context a shallow copy creates a new List instance but containing references to the original objects.

How do I copy the contents of one ArrayList into another?

You can use such trick:

myObject = new ArrayList<Object>(myTempObject);

or use

myObject = (ArrayList<Object>)myTempObject.clone();

You can get some information about clone() method here

But you should remember, that all these ways will give you a copy of your List, not all of its elements. So if you change one of the elements in your copied List, it will also be changed in your original List.

How can i copy an ArrayList without pointing to the objects in the source List in Java?

Simply you can create a copy constructor for Exon. then in foreach you must pass new Exon object.(with start=2)

A copy constructor: That's helpful when we want to copy a complex
object that has several fields, or when we want to make a deep copy of
an existing object.


1- Create copy constructor for Exon

public class Exon {

private int start;

//Copy constructor
public Exon(Exon exon) {
this.start = exon.getStart();
}

//Main Constructor and Getters and Setters

}

2- Create a copy from main list

 List<Exon> CopyList = mainList.stream().map(exon -> {
Exon copyExon = new Exon();
copyExon.setStart(2);
return new Exon(copyExon);
}).collect(Collectors.toList());

I wrote your code as follows:

public static void main(String[] args) {

//Initialize
ArrayList<Exon> mainList = new ArrayList<>();
Exon r1 = new Exon();
r1.setStart(5);
Exon r2 = new Exon();
r2.setStart(10);
Exon r3 = new Exon();
r3.setStart(15);
mainList.add(r1);
mainList.add(r2);
mainList.add(r3);

//Print mainList
System.out.println("Reg 1");
for (Exon e : mainList) {
System.out.println(e.getStart());
}

//Copy the mainList (I changed your foreach)
List<Exon> copyList = mainList.stream().map(exon -> {

//Create New Exon
Exon copyExon = new Exon(exon);
copyExon.setStart(2);
return copyExon ;

}).collect(Collectors.toList());

//Print copyList
System.out.println("Copy");
for (Exon e : copyList) {
System.out.println(e.getStart());
}

//Print mainList
System.out.println("Reg 1 - untouched");
for (Exon e : mainList) {
System.out.println(e.getStart());
}
}

Result :

Reg 1
5
10
15
Copy
2
2
2
Reg 1 - untouched
5
10
15

This link might be useful for Copy Constructor



Related Topics



Leave a reply



Submit