K Man
K Man

Reputation: 628

Object reference not affecting the object it refers to?

My understanding of Java is that if you have two references to the same object, any changes made to the object's state under one reference will be reflected under the other. Take this example of two List references (generics omitted for simplicity).

List list = Arrays.asList(1, 2, 3, 4, 5);
List list2 = list;
list2.set(0, 17);
System.out.println(list); //prints [17, 2, 3, 4, 5]

As predicted, modifying the contents of list has the same effect on list2 because they both refer to the same List object. However, I am getting unexpected results here.

Node head = new Node(0);
int[] numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9};
for(int number: numbers) head.appendToTail(number);
head.printNode(); //prints 0 1 2 3 4 5 6 7 8 9

Node target = head.next.next;
target = target.deleteNode(target, target.data);
head.printNode(); //prints 0 1 2 3 4 5 6 7 8 9

target is a reference to the Node object in head.next.next, so deleting it should have eliminated Node 2, but it did not. Replacing the last three lines with the following code will, however.

head.next.next = head.next.next.deleteNode(head.next.next, head.next.next.data);
head.printNode(); //prints 0 1 3 4 5 6 7 8 9

Of course, this is a lot more tedious, so I would have rather used the target reference. Why is this happening? You may not need it, but I will include my Node class down below just in case.

class Node {
    Node next = null;
    int data;

    public Node(int d) {
        data = d;
    }


    void printNode() {
        Node n = this;
        while (n != null) {
            System.out.print(n.data + " ");
            n = n.next;
        }
        System.out.println();
    }

    void appendToTail(int d) {
        Node end = new Node(d);
        Node n = this;
        while (n.next != null) {
            n = n.next;
        }
        n.next = end;
    }

    Node deleteNode(Node head, int d) {
        if (head == null) return null;

        Node n = head;

        if (n.data == d) {
            return head.next;
        }

        while (n.next != null) {
            if (n.next.data == d) {
                n.next = n.next.next;
                return head;
            }
            n = n.next;
        }
        return head;
    }
}

Upvotes: 0

Views: 53

Answers (1)

Phenomenal One
Phenomenal One

Reputation: 2587

Yes, it won't affect your code.

Consider this snippet in deleteNode function.

if (n.data == d) {
   return head.next;
}

Consider the addresses to be 100 -> 200 -> 300 -> 400 -> 500 -> ...

So, now we have ,

Node target = head.next.next;

The head node points to address 100 now. And target points to 300.

After this,

target = target.deleteNode(target, target.data);

Now, the if condition pointed above gets executed and target becomes 400. No actual deletion takes place.

Now, head node still intact and prints the entire list.

Consider the following for example.

target = target.deleteNode(target, target.next.data);
head.printNode(); //prints 0 1 2 4 5 6 7 8 9

So, your first node deletion logic does actually delete the node , but it simply returns the 2nd node.

If you want to change the original list

head.next.next = target.deleteNode(target, target.data);
head.printNode(); // prints 0 1 3 4 5 6 7 8 9 

Hope I clarified the issue.

Upvotes: 1

Related Questions