我对Java的理解是,如果对同一个对象有两个引用,在一个引用下对对象状态所做的任何更改都将反映在另一个引用中。以两个List引用为例(为了简单起见,省略了泛型(。
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]
正如预测的那样,修改list的内容对list2具有相同的效果,因为它们都引用了相同的list对象。然而,我在这里得到了意想不到的结果。
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是head.next.next中Node对象的引用,因此删除它本应消除Node 2,但它没有。但是,将最后三行替换为以下代码。
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
当然,这要乏味得多,所以我宁愿使用目标引用。为什么会发生这种情况?您可能不需要它,但我会在下面包含我的Node类,以防万一。
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;
}
}
请考虑deleteNode
函数中的这个片段。
if (n.data == d) {
return head.next;
}
考虑地址为100->200->300->400->500->。。
所以,现在我们有
Node target = head.next.next;
CCD_ 2节点现在指向地址100。CCD_ 3指向300。
之后,
target = target.deleteNode(target, target.data);
现在,执行上面指出的if
条件,并且target
变为400。没有实际删除。
现在,head节点仍然完好无损,并打印整个列表。
以下面的例子为例。
target = target.deleteNode(target, target.next.data);
head.printNode(); //prints 0 1 2 4 5 6 7 8 9
因此,您的第一个节点删除逻辑实际上删除了节点,但它只是返回第二个节点。
如果您想更改原始列表
head.next.next = target.deleteNode(target, target.data);
head.printNode(); // prints 0 1 3 4 5 6 7 8 9
希望我澄清了这个问题。