Вопрос о том, как связанный список ссылается и хранит данные

У меня вопрос о том, как Linked List хранит данные и ссылается друг на друга.

public class LinkedList {

    static class Node {
        int data;
        Node next;

        // Constructor
        Node(int d)
        {
            data = d;
            next = null;
        }
    }

    public static void main (String[] args) {
        Node first = new Node(1);
        Node second = new Node(2);
        Node third = new Node(3);
        Node fourth = new Node(4);
        Node fifth = new Node(5);

        first.next = second;
        second.next = third;
        third.next = fourth;
        fourth.next = fifth;

        second = fourth;
        System.out.println(second.data + "is fourth");
        while (first != null) {
            System.out.println(first.data);
            first = first.next;

        }
    }
}

Этот код распечатывает

4 is fourth
1
2
3
4
5

Тем не менее, я думал, что это должно быть

4 is fourth
1
4
5

Потому что я изменил «второе» значение на «четвертое» значение

Кто-нибудь может объяснить, что здесь происходит?

вы не меняете никаких значений. второй ссылается на четвертый, который содержит значение нового узла (4). Вам нужно написать first.next = четвертый, чтобы получить желаемый результат

digital illusion 21.12.2020 20:50

Вы поменяли вторую на четвертую, а не вторую на четвертую.

lainatnavi 21.12.2020 20:50

Спасибо за ответ, однако я не пытаюсь получить желаемый результат, но хочу знать, почему он все еще выводит «4 12345», когда выводится «second.data» 4. Не могли бы вы уточнить эту часть?

Happydoodle Pa 21.12.2020 21:02
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
3
192
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Важно понимать, что происходит, когда вы вызываете метод или создаете новую переменную в памяти, чтобы понять это поведение. По сути, в памяти есть две части, где данные хранятся для чего-то подобного — стек и куча. Стек хранит статическую информацию и имеет фиксированный размер, в то время как куча может хранить более сложные данные (например, объекты) и не имеет определенных ограничений по размеру, кроме объема доступной памяти.

Когда вы создаете экземпляр объекта в Java, сам объект (значения и свойства) определяется и сохраняется в куче, тогда как ссылка на данные или адрес памяти объекта в куче сохраняется в переменной на куча. Вот почему, когда вы делаете что-то вроде

ExampleObject o = new ExampleObject();
System.out.println(o);

печатает что-то вроде ExampleObject@fa243dsf

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

Теперь, чтобы вернуться к вашему вопросу, то же самое происходит со свойством next для каждого Node, оно хранит не сам объект, а ссылку на этот объект. Давайте представим, что это адреса памяти для каждого из созданных вами экземпляров Node (просто для примера, это не точные места, где они хранятся Java на вашем компьютере, и не правильные адреса памяти):

first has an address of 111
second has an address of 222
third has an address of 333
fourth has an address of 444
fifth has an address of 555

Теперь ваш LL выглядит так после присвоения следующих значений:

first.next = Node@222
second.next = Node@333
third.next = Node@444
fourth.next = Node@555
fifth.next = null

Теперь, когда Java достигает строки second = fourth, вы изменили не сами данные объекта, а только адрес памяти, на который указывает переменная second. Под этим я подразумеваю, что second теперь указывает на адрес 444, и если вы запустите System.out.println(second);, вы увидите, что Node@444 выводится на консоль, однако вы не изменили исходный объект, на который ссылается second, и не изменили значения LinkedList. Это означает, что значение по адресу памяти 222 не изменилось, и, поскольку first.next указывает на Node@222, значение Node, созданное и сохраненное по адресу 222, такое же, как оно было изначально. Вот почему, когда вы печатаете second.data в конце, вы получаете то же значение, что и fourth.data, но почему само LinkedList не изменилось до того, на что вы думали, что оно изменится. Если это объяснение все еще не очень ясно, я предлагаю вам изучить переменные, хранящие/передающие данные по ссылке и по значению, поскольку это концепция, которая описывает поведение, которое вы видите, по сравнению с тем, что вы ожидали.

Привет, Сал, я действительно ценю твой ответ! Теперь стало так ясно! Большое спасибо ! оцените это снова!

Happydoodle Pa 21.12.2020 21:27

Другие вопросы по теме