How to clone ArrayList and also clone its contents?

JavaCollectionsCloneDeep Copy

Java Problem Overview


How can I clone an ArrayList and also clone its items in Java?

For example I have:

ArrayList<Dog> dogs = getDogs();
ArrayList<Dog> clonedList = ....something to do with dogs....

And I would expect that objects in clonedList are not the same as in dogs list.

Java Solutions


Solution 1 - Java

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.

Solution 2 - Java

I, personally, would add a constructor to Dog:

class Dog
{
    public Dog()
    { ... } // Regular constructor

    public Dog(Dog dog) {
        // Copy all the fields of Dog.
    }
}

Then just iterate (as shown in Varkhan's answer):

public static List<Dog> cloneList(List<Dog> dogList) {
    List<Dog> clonedList = new ArrayList<Dog>(dogList.size());
    for (Dog dog : dogList) {
        clonedList.add(new Dog(dog));
    }
    return clonedList;
}

I find the advantage of this is you don't need to screw around with the broken Cloneable stuff in Java. It also matches the way that you copy Java collections.

Another option could be to write your own ICloneable interface and use that. That way you could write a generic method for cloning.

Solution 3 - Java

All standard collections have copy constructors. Use them.

List<Double> original = // some list
List<Double> copy = new ArrayList<Double>(original); //This does a shallow copy

clone() was designed with several mistakes (see this question), so it's best to avoid it.

From Effective Java 2nd Edition, Item 11: Override clone judiciously

> Given all of the problems associated with Cloneable, it’s safe to say > that other interfaces should not extend it, and that classes > designed for inheritance (Item 17) should not implement it. Because of > its many shortcomings, some expert programmers simply choose never to > override the clone method and never to invoke it except, perhaps, to > copy arrays. If you design a class for inheritance, be aware that if > you choose not to provide a well-behaved protected clone method, it > will be impossible for subclasses to implement Cloneable.

This book also describes the many advantages copy constructors have over Cloneable/clone.

  • They don't rely on a risk-prone extralinguistic object creation mechanism
  • They don't demand unenforceable adherence to thinly documented conventions
  • They don't conflict with the proper use of final fields
  • They don't throw unnecessary checked exceptions
  • They don't require casts.

Consider another benefit of using copy constructors: Suppose you have a HashSet s, and you want to copy it as a TreeSet. The clone method can’t offer this functionality, but it’s easy with a conversion constructor: new TreeSet(s).

Solution 4 - Java

Java 8 provides a new way to call the copy constructor or clone method on the element dogs elegantly and compactly: Streams, lambdas and collectors.

Copy constructor:

List<Dog> clonedDogs = dogs.stream().map(Dog::new).collect(toList());

The expression Dog::new is called a method reference. It creates a function object which calls a constructor on Dog which takes another dog as argument.

Clone method [1]:

List<Dog> clonedDogs = dogs.stream().map(Dog::clone).collect(toList());

Getting an ArrayList as the result

Or, if you have to get an ArrayList back (in case you want to modify it later):

ArrayList<Dog> clonedDogs = dogs.stream().map(Dog::new).collect(toCollection(ArrayList::new));

Update the list in place

If you don't need to keep the original content of the dogs list you can instead use the replaceAll method and update the list in place:

dogs.replaceAll(Dog::new);

All examples assume import static java.util.stream.Collectors.*;.


Collector for ArrayLists

The collector from the last example can be made into a util method. Since this is such a common thing to do I personally like it to be short and pretty. Like this:

ArrayList<Dog> clonedDogs = dogs.stream().map(d -> d.clone()).collect(toArrayList());

public static <T> Collector<T, ?, ArrayList<T>> toArrayList() {
    return Collectors.toCollection(ArrayList::new);
}

[1] Note on CloneNotSupportedException:

For this solution to work the clone method of Dog must not declare that it throws CloneNotSupportedException. The reason is that the argument to map is not allowed to throw any checked exceptions.

Like this:

    // Note: Method is public and returns Dog, not Object
    @Override
    public Dog clone() /* Note: No throws clause here */ { ...

This should not be a big problem however, since that is the best practice anyway. (Effectice Java for example gives this advice.)

Thanks to Gustavo for noting this.

Solution 5 - Java

Basically there are three ways without iterating manually,

1 Using constructor

ArrayList<Dog> dogs = getDogs();
ArrayList<Dog> clonedList = new ArrayList<Dog>(dogs);

2 Using addAll(Collection<? extends E> c)

ArrayList<Dog> dogs = getDogs();
ArrayList<Dog> clonedList = new ArrayList<Dog>();
clonedList.addAll(dogs);

3 Using addAll(int index, Collection<? extends E> c) method with int parameter

ArrayList<Dog> dogs = getDogs();
ArrayList<Dog> clonedList = new ArrayList<Dog>();
clonedList.addAll(0, dogs);

NB : The behavior of these operations will be undefined if the specified collection is modified while the operation is in progress.

Solution 6 - Java

I think the current green answer is bad , why you might ask?

  • It can require to add a lot of code
  • It requires you to list all Lists to be copied and do this

The way serialization is also bad imo, you might have to add Serializable all over the place.

So what is the solution:

Java Deep-Cloning library The cloning library is a small, open source (apache licence) java library which deep-clones objects. The objects don't have to implement the Cloneable interface. Effectivelly, this library can clone ANY java objects. It can be used i.e. in cache implementations if you don't want the cached object to be modified or whenever you want to create a deep copy of objects.

Cloner cloner=new Cloner();
XX clone = cloner.deepClone(someObjectOfTypeXX);

Check it out at https://github.com/kostaskougios/cloning

Solution 7 - Java

You can use JSON (with a JSON Library) to serialize and then unserialize the list. The serialized list holds no reference to the original object when unserialized.

Using Google GSON:

List<CategoryModel> originalList = new ArrayList<>(); // add some items later
String listAsJson = gson.toJson(originalList);
List<CategoryModel> newList = new Gson().fromJson(listAsJson, new TypeToken<List<CategoryModel>>() {}.getType());

You can also do it using other JSON libraries like Jackson.

The advantage of using this approach is that you can solve the problem without having to create classes, interfaces, and cloning logic (which can be very long if your object has other lists of objects inside)

Solution 8 - Java

I have used this option always:

ArrayList<Dog> clonedList = new ArrayList<Dog>(name_of_arraylist_that_you_need_to_Clone);

Solution 9 - Java

You will need to clone the ArrayList by hand (by iterating over it and copying each element to a new ArrayList), because clone() will not do it for you. Reason for this is that the objects contained in the ArrayList may not implement Clonable themselves.

Edit: ... and that is exactly what Varkhan's code does.

Solution 10 - Java

Some other alternatives for copying ArrayList as a Deep Copy

Alernative 1 - Use of external package commons-lang3, method SerializationUtils.clone():

SerializationUtils.clone()

Let's say we have a class dog where the fields of the class are mutable and at least one field is an object of type String and mutable - not a primitive data type (otherwise shallow copy would be enough).

Example of shallow copy:

List<Dog> dogs = getDogs(); // We assume it returns a list of Dogs
List<Dog> clonedDogs = new ArrayList<>(dogs);

Now back to deep copy of dogs.

The Dog class does only have mutable fields.

Dog class:

public class Dog implements Serializable {
    private String name;
    private int age;

    public Dog() {
        // Class with only mutable fields!
        this.name = "NO_NAME";
        this.age = -1;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Dog{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

Note that the class Dog implements Serializable! This makes it possible to utilize method "SerializationUtils.clone(dog)"

Read the comments in the main method to understand the outcome. It shows that we have successfully made a deep copy of ArrayList(). See below "SerializationUtils.clone(dog)" in context:

public static void main(String[] args) {
    Dog dog1 = new Dog();
    dog1.setName("Buddy");
    dog1.setAge(1);

    Dog dog2 = new Dog();
    dog2.setName("Milo");
    dog2.setAge(2);

    List<Dog> dogs = new ArrayList<>(Arrays.asList(dog1,dog2));

    // Output: 'List dogs: [Dog{name='Buddy', age=1}, Dog{name='Milo', age=2}]'
    System.out.println("List dogs: " + dogs);

    // Let's clone and make a deep copy of the dogs' ArrayList with external package commons-lang3:
    List<Dog> clonedDogs = dogs.stream().map(dog -> SerializationUtils.clone(dog)).collect(Collectors.toList());
    // Output: 'Now list dogs are deep copied into list clonedDogs.'
    System.out.println("Now list dogs are deep copied into list clonedDogs.");

    // A change on dog1 or dog2 can not impact a deep copy.
    // Let's make a change on dog1 and dog2, and test this
    // statement.
    dog1.setName("Bella");
    dog1.setAge(3);
    dog2.setName("Molly");
    dog2.setAge(4);

    // The change is made on list dogs!
    // Output: 'List dogs after change: [Dog{name='Bella', age=3}, Dog{name='Molly', age=4}]'
    System.out.println("List dogs after change: " + dogs);

    // There is no impact on list clonedDogs's inner objects after the deep copy.
    // The deep copy of list clonedDogs was successful!
    // If clonedDogs would be a shallow copy we would see the change on the field
    // "private String name", the change made in list dogs, when setting the names
    // Bella and Molly.
    // Output clonedDogs:
    // 'After change in list dogs, no impact/change in list clonedDogs:\n'
    // '[Dog{name='Buddy', age=1}, Dog{name='Milo', age=2}]\n'
    System.out.println("After change in list dogs, no impact/change in list clonedDogs: \n" + clonedDogs);
}

Output:

List dogs: [Dog{name='Buddy', age=1}, Dog{name='Milo', age=2}]
Now list dogs are deep copied into list clonedDogs.
List dogs after change: [Dog{name='Bella', age=3}, Dog{name='Molly', age=4}]
After change in list dogs, no impact/change in list clonedDogs:
[Dog{name='Buddy', age=1}, Dog{name='Milo', age=2}]

Comment: Since there is no impact/change on list clonedDogs after changing list dogs, then deep copy of ArrayList is successful!

Alernative 2 - Use of no external packages:

A new method "clone()" is introduced in the Dog class and "implements Serializable" is removed compare to alternative 1.

clone()

Dog class:

public class Dog {
    private String name;
    private int age;

    public Dog() {
        // Class with only mutable fields!
        this.name = "NO_NAME";
        this.age = -1;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    /**
     * Returns a deep copy of the Dog
     * @return new instance of {@link Dog}
     */
    public Dog clone() {
        Dog newDog = new Dog();
        newDog.setName(this.name);
        newDog.setAge(this.age);
        return newDog;
    }

    @Override
    public String toString() {
        return "Dog{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

Read the comments in the main method below to understand the outcome. It shows that we have successfully made a deep copy of ArrayList(). See below "clone()" method in context:

public static void main(String[] args) {
    Dog dog1 = new Dog();
    dog1.setName("Buddy");
    dog1.setAge(1);

    Dog dog2 = new Dog();
    dog2.setName("Milo");
    dog2.setAge(2);

    List<Dog> dogs = new ArrayList<>(Arrays.asList(dog1,dog2));

    // Output: 'List dogs: [Dog{name='Buddy', age=1}, Dog{name='Milo', age=2}]'
    System.out.println("List dogs: " + dogs);

    // Let's clone and make a deep copy of the dogs' ArrayList:
    List<Dog> clonedDogs = dogs.stream().map(dog -> dog.clone()).collect(Collectors.toList());
    // Output: 'Now list dogs are deep copied into list clonedDogs.'
    System.out.println("Now list dogs are deep copied into list clonedDogs.");

    // A change on dog1 or dog2 can not impact a deep copy.
    // Let's make a change on dog1 and dog2, and test this
    // statement.
    dog1.setName("Bella");
    dog1.setAge(3);
    dog2.setName("Molly");
    dog2.setAge(4);

    // The change is made on list dogs!
    // Output: 'List dogs after change: [Dog{name='Bella', age=3}, Dog{name='Molly', age=4}]'
    System.out.println("List dogs after change: " + dogs);

    // There is no impact on list clonedDogs's inner objects after the deep copy.
    // The deep copy of list clonedDogs was successful!
    // If clonedDogs would be a shallow copy we would see the change on the field
    // "private String name", the change made in list dogs, when setting the names
    // Bella and Molly.
    // Output clonedDogs:
    // 'After change in list dogs, no impact/change in list clonedDogs:\n'
    // '[Dog{name='Buddy', age=1}, Dog{name='Milo', age=2}]\n'
    System.out.println("After change in list dogs, no impact/change in list clonedDogs: \n" + clonedDogs);
}

Output:

List dogs: [Dog{name='Buddy', age=1}, Dog{name='Milo', age=2}]
Now list dogs are deep copied into list clonedDogs.
List dogs after change: [Dog{name='Bella', age=3}, Dog{name='Molly', age=4}]
After change in list dogs, no impact/change in list clonedDogs:
[Dog{name='Buddy', age=1}, Dog{name='Milo', age=2}]

Comment: Since there is no impact/change on list clonedDogs after changing list dogs, then deep copy of ArrayList is successful!

Note1: Alternative 1 is much slower than Alternative 2, but easier to mainatain since you do not need to upadate any methods like clone().

Note2: For alternative 1 the following maven dependency was used for method "SerializationUtils.clone()":

<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
    <version>3.9</version>
</dependency>

Find more releases of common-lang3 at:

https://mvnrepository.com/artifact/org.apache.commons/commons-lang3

Solution 11 - Java

for you objects override clone() method

class You_class {

    int a;

    @Override
    public You_class clone() {
        You_class you_class = new You_class();
        you_class.a = this.a;
        return you_class;
    }
}

and call .clone() for Vector obj or ArraiList obj....

Solution 12 - Java

A nasty way is to do it with reflection. Something like this worked for me.

public static <T extends Cloneable> List<T> deepCloneList(List<T> original) {
    if (original == null || original.size() < 1) {
        return new ArrayList<>();
    }

    try {
        int originalSize = original.size();
        Method cloneMethod = original.get(0).getClass().getDeclaredMethod("clone");
        List<T> clonedList = new ArrayList<>();

        // noinspection ForLoopReplaceableByForEach
        for (int i = 0; i < originalSize; i++) {
            // noinspection unchecked
            clonedList.add((T) cloneMethod.invoke(original.get(i)));
        }
        return clonedList;
    } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
        System.err.println("Couldn't clone list due to " + e.getMessage());
        return new ArrayList<>();
    }
}

Solution 13 - Java

List<Dog> dogs;
List<Dog> copiedDogs = dogs.stream().map(dog -> SerializationUtils.clone(dog)).Collectors.toList());

This will deep copy each dog

Solution 14 - Java

The other posters are correct: you need to iterate the list and copy into a new list.

However... If the objects in the list are immutable - you don't need to clone them. If your object has a complex object graph - they will need to be immutable as well.

The other benefit of immutability is that they are threadsafe as well.

Solution 15 - Java

Here is a solution using a generic template type:

public static <T> List<T> copyList(List<T> source) {
    List<T> dest = new ArrayList<T>();
    for (T item : source) { dest.add(item); }
    return dest;
}

Solution 16 - Java

Easy way by using commons-lang-2.3.jar that library of java to clone list

link download commons-lang-2.3.jar

How to use

oldList.........
List<YourObject> newList = new ArrayList<YourObject>();
foreach(YourObject obj : oldList){
   newList.add((YourObject)SerializationUtils.clone(obj));
}

I hope this one can helpful.

:D

Solution 17 - Java

The package import org.apache.commons.lang.SerializationUtils;

There is a method SerializationUtils.clone(Object);

Example

this.myObjectCloned = SerializationUtils.clone(this.object);

Solution 18 - Java

I have just developed a lib that is able to clone an entity object and a java.util.List object. Just download the jar in https://drive.google.com/open?id=0B69Sui5ah93EUTloSktFUkctN0U and use the static method cloneListObject(List list). This method not only clones the List but also all entity elements.

Solution 19 - Java

The below worked for me..

in Dog.java

public Class Dog{

private String a,b;

public Dog(){} //no args constructor

public Dog(Dog d){ // copy constructor
   this.a=d.a;
   this.b=d.b;
}

}

 -------------------------

 private List<Dog> createCopy(List<Dog> dogs) {
 List<Dog> newDogsList= new ArrayList<>();
 if (CollectionUtils.isNotEmpty(dogs)) {
 dogs.stream().forEach(dog-> newDogsList.add((Dog) SerializationUtils.clone(dog)));
 }
 return newDogsList;
 }

Here the new list which got created from createCopy method is created through SerializationUtils.clone(). So any change made to new list will not affect original list

Solution 20 - Java

Simple way is

ArrayList<Dog> dogs = getDogs();
ArrayList<Dog> clonedList = new ArrayList<Dog>(dogs);

Solution 21 - Java

I think I found a really easy way to make a deep copy ArrayList. Assuming you want to copy a String ArrayList arrayA.

ArrayList<String>arrayB = new ArrayList<String>();
arrayB.addAll(arrayA);

Let me know if it doesn't work for you.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionpaligView Question on Stackoverflow
Solution 1 - JavaVarkhanView Answer on Stackoverflow
Solution 2 - JavacdmckayView Answer on Stackoverflow
Solution 3 - JavaRose PerroneView Answer on Stackoverflow
Solution 4 - JavaLiiView Answer on Stackoverflow
Solution 5 - JavajavatarView Answer on Stackoverflow
Solution 6 - JavaCojonesView Answer on Stackoverflow
Solution 7 - JavaRenato ProbstView Answer on Stackoverflow
Solution 8 - JavabesartmView Answer on Stackoverflow
Solution 9 - JavaStephan202View Answer on Stackoverflow
Solution 10 - JavaDigitShifterView Answer on Stackoverflow
Solution 11 - JavaRN3KK NickView Answer on Stackoverflow
Solution 12 - JavamilosmnsView Answer on Stackoverflow
Solution 13 - JavaRaju KView Answer on Stackoverflow
Solution 14 - JavaFortyrunnerView Answer on Stackoverflow
Solution 15 - JavaAndrew CoyteView Answer on Stackoverflow
Solution 16 - JavasonidaView Answer on Stackoverflow
Solution 17 - JavapachecoView Answer on Stackoverflow
Solution 18 - JavaEduardo de MeloView Answer on Stackoverflow
Solution 19 - Javagayu312View Answer on Stackoverflow
Solution 20 - JavaThangaView Answer on Stackoverflow
Solution 21 - JavajordanrhView Answer on Stackoverflow