By palig


2009-04-03 20:40:28 8 Comments

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.

17 comments

@Lii 2015-11-03 19:36:05

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(d -> d.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.


PS:

If you find it prettier you can instead use the method reference syntax to do exactly the same thing:

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

@SaurabhJinturkar 2016-07-28 23:55:47

Do you see any performance impact of doing this way where Dog(d) is copy constructor? List<Dog> clonedDogs = new ArrayList<>(); dogs.stream().parallel().forEach(d -> clonedDogs.add(new Dog(d)));

@Lii 2016-07-29 15:36:52

@SaurabhJinturkar: Your version is not thread-safe and should not be used with parallel streams. That is because the parallel call makes clonedDogs.add get called from multiple threads at the same time. The versions which uses collect are thread-safe. This is one of the advantages of the functional model of the stream library, the same code can be used for parallel streams.

@Lii 2016-07-29 15:39:19

@SaurabhJinturkar: Also, the collect operation is fast. It does pretty much the same thing as your version does, but also work for parallel streams. You could fix your version by using, for example, a concurrent queue instead of an array list, but I'm almost certain that would be much slower.

@Gustavo 2016-08-23 14:25:49

Whenever I try to use your solution I get an Unhandled exception type CloneNotSupportedException on d.clone(). Declaring the exception or catching it doesn't solve it.

@Lii 2016-08-23 15:06:39

@Gustavo: That is almost certainly because the object you are cloning, (Dog in this example) does not support cloning. Are you sure it implements the Clonable interface?

@Gustavo 2016-08-23 15:16:09

@Lii It does. Plus it overrides clone(). I had to change my clone() not to throw any exceptions.

@Lii 2016-08-23 15:31:17

@Gustavo: Ah, now I understand, I thought you got an exception at runtime but you got a compilation error. Yes, alas, it is very inconvenient to work with checked exceptions together with streams and lambdas. I believe it is okay in this case however, because I think the best practice when overriding clone is to do what you did and not declare the exception (since you don't plan on throwing it anyway). I'll add a note about that to the answer. Thanks!

@Yogen Rai 2017-04-17 21:51:06

@Lii As stream is functional in nature, meaning an operation on a stream produces a result, but does not modify its source., to my understanding, we do not need to use map. So, we can directly use, List<Dog> clonedList = dogs.stream().collect(Collectors.toList()); Oracle Doc

@Lii 2017-04-18 08:32:04

@YogenRai: No, this is not the case. Your line of code would give a shallow copy of the list; the result would be new list, but it would contain the same Dog objects. The "source list" would not be modified, but any future modification of the content dogs would modify the same dogs as in the source. This question is about creating new dog objects in a new list. This is what is called a deep copy.

@Yogen Rai 2017-04-18 14:22:01

@Lii Ya you are right :) I didn't notice that change in any of element in dogs and vice versa with cloned list will be reflected on both of them. And, as others pointed out, I think copy constructor would be the best option to create new copy. So, our lamda would be List<Dog> clonedList = dogs.stream().map(Dog::new).collect(Collectors.toList()); and I have copy constructor there in Dog class. But anyway, thanks

@Lii 2017-04-19 10:57:57

@YogenRai: You're right, it's better with a copy constructors. I'll add that to the answer.

@Varkhan 2009-04-03 20:43:23

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.

@Michael Myers 2009-04-03 20:47:21

You can't do it generically, though. clone() is not part of the Cloneable interface.

@Michael Myers 2009-04-03 20:49:08

But clone() is protected in Object, so you can't access it. Try compiling that code.

@Stephan202 2009-04-03 20:50:01

All classes extend Object, so they can override clone(). This is what Cloneable is for!

@Jose Chavez 2009-04-03 20:50:30

This is a good answer. Cloneable is actually an interface. However, mmyers has a point, in that the clone() method is a protected method declared in the Object class. You would have to override this method in your Dog class, and do the manual copying of fields yourself.

@Michael Myers 2009-04-03 20:51:30

@Jose: Yes, you could do this with a specific class that has overriden clone() to make it public. But you can't do it generically; that's my point.

@Varkhan 2009-04-03 20:51:33

@mmyers My bad. Yes, I knew that the Cloneable iface was pretty f***ed up, but I hadn't realized to what extent.

@Jose Chavez 2009-04-03 20:51:45

Also, Cloneable is just a signature interface, like Serializable. Even if you overwrite the clone() method in the Object class, if your class does not implement Cloneable, then the javac compiler will throw an error.

@Michael Myers 2009-04-03 20:53:11

@Jose: Well, technically, you don't have to call super.clone() in your clone() method, so you don't absolutely have to implement Cloneable. See why nobody likes Cloneable? :D

@Stephan202 2009-04-03 20:53:34

The idea of the Cloneable interface is that of a ``contract'': a promise to sensibly implement clone(). It is true that Dog needs to override clone() and then implement the interface.

@Jose Chavez 2009-04-03 20:54:05

@mmyers You're right. Generically this wont work, because the interface and the method not defined in the same space. Good point.

@Jose Chavez 2009-04-03 20:55:32

I say, create a factory or builder, or even just a static method, that will take an instance of Dog, and manually copy fields to a new instance, and return that new instance.

@Varkhan 2009-04-03 20:57:54

@JoseChavez Yes, that would be a better design pattern. However the OP mentions cloning, which may be an imposed requirement.

@Michael Myers 2009-04-03 21:00:34

+1 for your refactored method.

@palig 2009-04-03 22:21:30

Thanks for really fast answer guys!

@cdmckay 2013-02-04 14:57:32

Should also point out that clone() does not call the constructor, which may cause some problems for certain classes.

@milosmns 2016-04-15 12:57:04

A good practice would be to have a constructor on the Dog class which takes in exactly 1 parameter - a Dog object - and "clone" using that constructor. But yeah... nobody really likes cloneables :)

@hyyou2010 2017-10-19 03:21:57

I suggest to never use a function named as "clone". Always use a function that named as "deepClone" or "shallowClone".

@besartm 2018-05-18 07:20:16

I have used this option always:

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

@Antonio Vlasic 2019-07-17 06:32:08

Uhm, I don't know why no one upvotes that, but it works. Thanks buddy!

@Eduardo de Melo 2017-05-11 23:28:53

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.

@Cojones 2009-08-07 05:58:58

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

@cdmckay 2010-06-21 06:24:29

One caveat with this method is that it uses reflection, which can be quite a bit slower than Varkhan's solution.

@nawfal 2013-08-07 10:41:30

I dont understand the first point "it requires a lot of code". The library you're talking about would need more code. Its only a matter of where you place it. Otherwise I agree a special library for this kind of thing helps..

@Stuart Marks 2017-02-07 16:19:58

The Google Code link now redirects to github.com/kostaskougios/cloning

@jordanrh 2016-11-23 22:24:09

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.

@djdance 2017-08-14 11:06:51

doesn't work if you use List<List<JsonObject>> for example in my case

@Christian Fries 2018-08-03 14:57:26

Strings are immutable. Cloning does not make sense and in your example arrayB and arrayA have the same object references - its a shallow copy.

@javatar 2015-02-18 13:05:05

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.

@electrobabe 2016-03-15 13:57:50

please not that all of these 3 variants only create shallow copies of the lists

@Neeson.Z 2016-10-12 01:55:57

This is not A deep clone, those two lists retain the same objects, just copied the references only but the Dog objects, once you modified either list, the next list will have the same change. donno y so many upvotes.

@Alessandro Teruzzi 2018-06-07 15:08:43

@Neeson.Z All methods create a deep copy of the list and a shallow copies of the element of the list. If you modify an element of the list the change will be reflected by the other list, but if you modify one of the list (for example removing an object), the other list will be unchanged.

@sagits 2016-06-09 21:44:16

I have found a way, you can use json to serialize/unserialize the list. The serialized list holds no reference to the original object when unserialized.

Using 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 do that using jackson and any other json library too.

@Satish 2018-03-22 18:13:02

I don't know why people have downvoted this answer. Other answers have to implement clone() or have to change their dependencies to include new libraries. But JSon library most of projects would have already included. I upvoted for this.

@Parag Pawar 2018-12-19 15:29:04

@Satish Yes, this is the only answer which helped me, I'm not sure what's wrong with others, but no matter what I did, clone or use copy constructor, my original list used to get updated, but this way it does not, so thanks to the author!

@marcRDZ 2019-08-07 07:24:33

Well, it's true that is not a pure Java reply for the knowledge´s sake but an efficient solution to deal with this issue quickly

@Stephan202 2009-04-03 20:46:06

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.

@Michael Myers 2009-04-03 20:48:31

And even if they do, there's no way to access clone() other than reflection, and it's not guaranteed to succeed anyway.

@erickson 2009-04-03 20:50:55

Varkhan's answer is wrong.

@Stephan202 2009-04-03 20:50:57

Let's keep the discussion under Varkhan's post :)

@erickson 2009-04-03 20:53:38

I'm referring to the citation of Varkhan's answer by this answer.

@Stephan202 2009-04-03 21:04:10

@erickson: I posted my comment in parallel with yours. Anyway, answer is updated.

@milosmns 2015-10-01 20:59:54

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<>();
    }
}

@Lii 2016-08-24 07:44:26

Neat and nasty trick! One potential problem: If original contains objects of different classes I think cloneMethod.invoke will fail with an exception when it is invoked with the wrong kind of object. Because of this it might be better to retrieve a specific clone Method for each object. Or use the clone method on Object (but since that one is protected that might fail in more cases).

@Lii 2016-08-24 07:46:53

Also, I think it would be better to throw a runtime exception in the catch-clause instead of returning an empty list.

@Rose Perrone 2012-04-10 04:30:40

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).

@Abdull 2012-11-29 17:30:50

As much as I'm aware of, the copy constructors of the standard collections create a shallow copy, not a deep copy. The question asked here looks for a deep copy answer.

@NimChimpsky 2013-02-13 15:41:55

this simply wrong, copy constuctors do a shallow copy - the whol epoint of te question

@Noumenon 2015-08-15 20:55:05

What's right about this answer is that if you are not mutating the objects in the list, adding or removing items doesn't remove them from both lists. It's not as shallow as simple assignment.

@pacheco 2013-05-02 19:25:00

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

There is a method SerializationUtils.clone(Object);

Example

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

@moskito-x 2013-05-02 19:49:43

it's a little bit outdated to answer this question. And many other answers in the comment down under the question.

@sonida 2013-04-04 16:20:19

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

@informatik01 2013-04-30 21:59:36

Just a note: why such an old version of Commons Lang? See the release history here: commons.apache.org/proper/commons-lang/release-history.html

@RN3KK Nick 2012-09-10 13:45:30

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....

@Andrew Coyte 2012-03-20 23:31:25

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;
}

@David Snabel-Caunt 2012-03-20 23:42:36

Generics are good but you also need to clone the items to answer the question. See stackoverflow.com/a/715660/80425

@cdmckay 2009-04-03 22:02:18

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.

@helpermethod 2010-03-15 21:46:50

+1 A copy constructor is the way to go. Also like the idea of an ICloneable interface.

@Micer 2013-04-21 20:17:10

Nice and easy solution, I like it!

@Dr. aNdRO 2014-04-23 15:05:18

can you be more specific with copy all the fields of DOG. I am realy not understanding :(

@Tobi G. 2016-02-14 23:01:59

Is it possible to write that function for an undefined Object (instead of Dog)?

@cdmckay 2016-02-15 01:17:49

@TobiG. I don't understand what you mean. Do you want cloneList(List<Object>) or Dog(Object)?

@Tobi G. 2016-02-17 02:31:32

@cdmckay One Function that works for cloneList(List<Object>), cloneList(List<Dog>) and cloneList(List<Cat>). But you can't call a generic Constructor I guess...?

@cdmckay 2016-02-17 15:35:14

@TobiG. Like a general cloning function then? That's not really what this question is about.

@milosmns 2016-04-15 12:59:10

As @helpermethod stated, this is a common pattern that is both clean and simple to understand.

@Fortyrunner 2009-04-04 10:12:21

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.

Related Questions

Sponsored Content

42 Answered Questions

[SOLVED] How do I convert a String to an int in Java?

55 Answered Questions

[SOLVED] Creating a memory leak with Java

69 Answered Questions

[SOLVED] What is the most efficient way to deep clone an object in JavaScript?

64 Answered Questions

[SOLVED] How do I correctly clone a JavaScript object?

58 Answered Questions

[SOLVED] How do I read / convert an InputStream into a String in Java?

15 Answered Questions

[SOLVED] How to clone or copy a list?

34 Answered Questions

[SOLVED] Create ArrayList from array

45 Answered Questions

[SOLVED] Deep cloning objects

  • 2008-09-17 00:06:27
  • NakedBrunch
  • 761152 View
  • 2096 Score
  • 45 Answer
  • Tags:   c# .net clone

30 Answered Questions

[SOLVED] Initialization of an ArrayList in one line

31 Answered Questions

[SOLVED] When to use LinkedList over ArrayList in Java?

Sponsored Content