Deep Clone Collection Objects in Java [Snippets]
Check out this post on how to deep clone an object in Java 8 using the Object.clone method and new Java streams.
Join the DZone community and get the full member experience.
Join For FreeDeep cloning of an object has always been something that Java developers work on constantly. There are a lot of articles that talk about the different ways to clone objects deeply and obviously. The preferred method is to use Copy Constructors
since it overcomes the design issues of Object.clone()
and provides better control over object construction.
Clone an Object
For example, if I want to have a deep copy of the Dog
object, then I would use constructor as:
class Dog {
private String name;
private int age;
public Dog(String name, int age) {
super();
this.name = name;
this.age = age;
}
//copy constructor to create the copy of the Dog object
public Dog(Dog dog) {
this.name = dog.name;
this.age = dog.age;
}
// getters and setters
}
Some of the notable advantages of using them over Objects.clone()
are:
- This doesn't force us to implement any interface or throw an exception, but we can surely do it if it is required.
- This allows us to have complete control over object creation; we can write our initialization logic in it.
Clone a Collection
With new feature Streams
introduced in Java 8, it has been the easiest ever to clone the collections, because when a stream
is created, the instance will not modify its source. This allows the creation of multiple instances from a single source.
For example, if the List of Dogs
can be cloned as below:
Dog dog1 = new Dog("Puppy", 4);
Dog dog2 = new Dog("Tom", 5);
Dog dog3 = new Dog("Hen", 3);
Dog dog4 = new Dog("Jen", 7);
List<Dog> dogs = new ArrayList<>();
dogs.add(dog1);
dogs.add(dog2);
dogs.add(dog3);
dogs.add(dog4);
//clone with java 8
List<Dog> clonedList = dogs.stream().map(Dog::new).collect(Collectors.toList());
Now, any modification you make to the original collection doesn't affect the cloned collection and vice-versa.
//clone with java 8
List<Dog> clonedList = dogs.stream().map(Dog::new).collect(Collectors.toList());
assertThat(dogs, is(clonedList));
// modify original list
dogs.remove(0);
// make sure cloned list remains unaffected
assertEquals(3, dogs.size());
assertEquals(4, clonedList.size());
// modify cloned list
clonedList.add(new Dog("New", 3));
// make sure original list remains unaffected
assertEquals(3, dogs.size());
assertEquals(5, clonedList.size());
// modify element in dogs
dog2.setName("Very New Name");
assertEquals("Very New Name", dogs.get(0).getName());
assertEquals("Tom", clonedList.get(1).getName());
The source code for the example presented above is available on GitHub.
Published at DZone with permission of Yogen Rai, DZone MVB. See the original article here.
Opinions expressed by DZone contributors are their own.
Comments