мелкая копия связного списка не отражает изменений при добавлении нового узла - PullRequest
5 голосов
/ 09 марта 2019

diagram Я много читал, но, похоже, я не могу очистить свое замешательство, не спросив здесь.Основываясь на диаграмме, когда я создаю поверхностную копию связанного списка, используя clone ().Создается новый связанный список, и эталонное значение переменной head в оригинале копируется в клон, а остальные узлы используются совместно.Так что, если я добавлю новый узел, используя клон, это должно быть видно для оригинала, не так ли?Но при печати list1 значение 3 опускается.Может кто-нибудь сказать мне, почему?

LinkedList<Integer> list1 = new LinkedList<>();
l1.add(1);
l1.add(2);
LinkedList<Integer> list2 = (LinkedList) l1.clone();
l2.add(3); 

Ответы [ 2 ]

1 голос
/ 09 марта 2019

clone() создает новую структуру LinkedList и возвращает новую ссылку на первый узел.Отношение между этими двумя LinkedList s заключается в том, что они совместно используют один и тот же узел values.Когда вы выполняете некоторые операции add \ remove со старым или новым списком, эти операции не изменят другой список.Вот почему мы делаем copy - мы не хотим изменять исходную структуру связанного списка при изменении копии.

Из LinkedList.clone документации:

Возвращает поверхностную копиюэто LinkedList.(Сами элементы не клонируются .) @return поверхностная копия этого LinkedList экземпляра

Рассмотрим пример ниже:

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]

Как мы видим, когда мы меняем внутреннее состояние первого элемента из первого списка, оно также видно и для второго списка.Таким образом, нет глубокой копии каждого значения элемента, а есть копия структуры - копия узлов и порядок.

Чтобы сделать это абсолютно ясным, давайте посмотрим на реализацию в 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.

0 голосов
/ 09 марта 2019

Метод clone () создает точную копию первого связанного списка и затем возвращает его в l2 здесь. Что делает, это создает новый экземпляр и копирует все поля из исходного, а затем возвращает его объекту l2. Если нам нужна только мелкая копия, мы можем просто использовать оператор присваивания, в этом случае любые изменения, внесенные в l1, отразятся на l2, поскольку новый объект не создается, а создается только копия ссылки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...