添加新节点时,链表的浅表副本无法反映更改 [英] shallow copy of linkedlist does not reflect changes when adding new node

查看:34
本文介绍了添加新节点时,链表的浅表副本无法反映更改的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经读了很多书,但是好像我不问这里就无法消除我的困惑.基于该图,当我使用clone()创建链表的浅表副本时.创建一个新的链表,并将原始变量中head变量的引用值复制到克隆的变量中,并共享其余节点.因此,如果我使用克隆添加一个新节点,原始节点应该可以看到它,不是吗?但是,当打印出list1时,将省略值3.有人可以告诉我为什么吗?

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

推荐答案

clone()创建新的 LinkedList 结构,并将新引用返回给第一个节点.这两个 LinkedList 之间的关系是它们共享相同的节点 .当您在旧列表或新列表上执行某些 add \ remove 操作时,这些操作将不会更改其他列表.这就是为什么我们要进行 copy 的原因-我们不想在更改副本时更改原始链表的结构.

clone() creates new LinkedList structure and returns new reference to first node. Relation between these two LinkedLists 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.

来自 LinkedList.clone 文档:

返回此 LinkedList 的浅表副本.(元素本身未克隆.)@return 这个 LinkedList 实例的浅拷贝

Returns a shallow copy of this LinkedList. (The elements themselves are not cloned.) @return a shallow copy of this LinkedList instance

请考虑以下示例:

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

上面的代码显示:

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

要明确地说,让我们看一下 Java 8 中的实现:

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

看看 for-each 循环.它遍历原始列表,并将值添加到 clone 列表.方法 add 创建一个新的 Node 对象,该对象存储与原始列表相同的值: x.item .

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.

这篇关于添加新节点时,链表的浅表副本无法反映更改的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆