在下面的示例中,在“main”中,将 LinkedList l1 克隆到 l2 后,当我将元素添加到 l2 时,我在 l1 中没有得到 300。
但是,在“addTwoLists”方法中,当我使用自定义实现时,将任何元素添加到“rohit”也会将其添加到“first”。
package hackerrank;
import java.util.LinkedList;
import java.util.concurrent.atomic.AtomicInteger;
class Node1 implements Cloneable{
int data;
Node1 next;
Node1(int x){
this.data=x;
this.next=null;
}
Node1 (){
}
protected Node1 clone() throws CloneNotSupportedException {
return (Node1) super.clone();
}
}
public class MS_linkedlist_copy {
public static void main(String[] args) {
// TODO Auto-generated method stub
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);
Node1 first = new Node1(1);
Node1 second = new Node1(2);
first.next= second;
Node1 third = new Node1(3);
Node1 fourth = new Node1(4);
third.next=fourth;
addTwoLists(first, third);
}
static Node1 reverse(Node1 head){
Node1 prev =null;
while(head!=null){
Node1 next_node = head.next;
head.next = prev;
prev=head;
head=next_node;
}
return prev;
}
//
static Node1 addTwoLists(Node1 first, Node1 second){
System.out.println(first.data);
Node1 rohit = null;
try {
rohit = (Node1)first.clone();
} catch (CloneNotSupportedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
rohit.data=1000;
rohit.next.data=1000;
System.out.println(first.data);
System.out.println(rohit.data);
Node1 rohit2= rohit;
while(rohit.next!=null) {
rohit= rohit.next;
}
Node1 rohit_add = new Node1(2000);
rohit.next = rohit_add;
System.out.println(first.data);
System.out.println(rohit2.data);
// rohit = first;
// rohit= reverse(rohit);
// reverse(second);
// System.out.println(first.data);
// System.out.println(rohit.data);
return null;
}
}
我尝试将元素添加到自定义的浅拷贝中,该副本已成功添加到主列表中。但是,在尝试将元素添加到内置 LinkedList 的浅拷贝后,这些元素不会添加到原始列表中。我试图了解内置 LinkedList 中发生了什么。
最佳答案
不同之处在于 LinkedList.clone
还会复制整个链表中的所有节点,而 Node1.clone
仅复制一个节点,而不是链接到它的任何节点。
您可以找到 LinkedList.clone
的实现 here ,
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;
}
请注意,它在循环中对克隆列表(此处称为clone
)调用add
。每次调用 add
都会创建一个新的链表节点。
请注意,这仍然是浅拷贝,因为节点中的数据没有被克隆。例如,如果列表存储 String
对象,则不会创建新字符串。
因此,克隆之后,您实际上会得到两个带有内置 LinkedList
的“链”:
O-O-O
O-O-O
而对于您的 Node1
,由于只克隆了一个节点,因此您会得到如下所示的结果:
first -> O
\
-O-O
/
rohit2 -> O
列表的两个“头”共享相同的“尾”,因此向列表末尾添加一个元素会将其添加到两个列表中。
您可以重写您的克隆
,以便它复制所有节点。一种简单的方法是递归地执行:
protected Node1 clone() throws CloneNotSupportedException {
Node1 newNode = new Node1(this.data);
if (next != null) {
newNode.next = next.clone();
}
return newNode;
}
关于java - 为什么 Java 中 LinkedList.add() 的内置实现不将元素添加到 LinkedList 的浅副本,而是自定义实现添加?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/75498323/