ArrayList clone() method in Java with Examplesclone() method is used to create a shallow copy of the mentioned array list. It just creates a copy of the list. Parameters: This method does not take any parameters. Return Value: This function returns a copy of the instance of Linked list.
The Java ArrayList clone() method makes the shallow copy of an array list. Here, the shallow copy means it creates copy of arraylist object. To learn more on shallow copy, visit Java Shallow Copy. Here, arraylist is an object of the ArrayList class.
ArrayList clone() method is used to create a shallow copy of the list.
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.
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.
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.
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)
.
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());
ArrayList
as the resultOr, 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));
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.*;
.
ArrayList
sThe 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);
}
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.
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.
I think the current green answer is bad , why you might ask?
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
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)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With