I have done a lot of readings but seems like I can't clear my confusion without asking here. Based on the diagram, when I create a a shallow copy of a linkedlist using clone(). A new linkedlist is created and the reference value of the head variable in the original is copied to the clone's and the rest of the nodes are shared. So if I add a new node using the clone, this should be visible to the orginal is it not? But when printing list1 out the value 3 is omitted. Can someone tell me why?
LinkedList<Integer> list1 = new LinkedList<>();
l1.add(1);
l1.add(2);
LinkedList<Integer> list2 = (LinkedList) l1.clone();
l2.add(3);
A linkedlist is just a class with one field which is a ref to a head node. Each node is an individual object which contains a ref to its next. Like you said, a shallow copy doesn't copy the node. So when i add a new node, the current last node's next variable refers to the next node.
In Shallow copy, a copy of the original object is stored and only the reference address is finally copied. In Deep copy, the copy of the original object and the repetitive copies both are stored.
LinkedList implements the Collection (and List) interface, so given an index i of an element in the list list , you can get previous and next elements with list. get(i-1) and list. get(i+1) , respectively.
Deep copy is performed by implementing our own copy constructor.
clone()
creates new LinkedList
structure and returns new reference to first node. Relation between these two LinkedList
s is they share same node values
. When you make some add
\ remove
operations on old or new list these operations will not change other list. This is why we do copy
- we do not want to change original linked list structure when we change copy.
From LinkedList.clone
documentation:
Returns a shallow copy of this
LinkedList
. (The elements themselves are not cloned.)@return
a shallow copy of thisLinkedList
instance
Consider below example:
import java.util.LinkedList;
import java.util.concurrent.atomic.AtomicInteger;
public class LinkedListsApp {
public static void main(String[] args) throws Exception {
LinkedList<AtomicInteger> l1 = new LinkedList<>();
l1.add(new AtomicInteger(100));
l1.add(new AtomicInteger(200));
LinkedList<AtomicInteger> l2 = (LinkedList) l1.clone();
l2.add(new AtomicInteger(300));
System.out.println(l1);
System.out.println(l2);
// change element on first list
l1.get(0).incrementAndGet();
System.out.println();
System.out.println("After change internal state of first element");
System.out.println(l1);
System.out.println(l2);
}
}
Above code prints:
[100, 200]
[100, 200, 300]
After change internal state of first element
[101, 200]
[101, 200, 300]
As we can see, when we change internal state of first element from first list it is visible for second list as well. So, there is no deep copy of each element value rather copy of structure - copy of nodes and order.
To make it absolutely clear, let's take a look on implementation in Java 8
:
public Object clone() {
LinkedList<E> clone = superClone();
// Put clone into "virgin" state
clone.first = clone.last = null;
clone.size = 0;
clone.modCount = 0;
// Initialize clone with our elements
for (Node<E> x = first; x != null; x = x.next)
clone.add(x.item);
return clone;
}
Take a look on for-each
loop. It iterates over original list and adds values to clone
list. Method add
creates new Node
object which stores the same value as original list: x.item
.
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