所以我有一个充满节点的数组,称为“SNode
s”(它们是我自己创建的类。它们实际上只是一个基本节点,它包含一个String和一个指向下一个节点的指针)
我有一个名为insertValue()
的方法,它接受你想要输入值的索引和你希望SNode
包含的字符串。但是,如果传递的索引中已包含SNode
,我希望新值成为SNode
的“下一个”节点(实质上是在每个索引空间中创建一个链接的节点列表)。
private int insertValue(int arrayPos, String element){//Checks for collisions with another SNode, and inserts the SNode into the apppropriate spot in the array
SNode targetNode = array[arrayPos];//What I want to be a reference to the node at the desired position in the array
while (targetNode != null){//If an SNode already exists in that position, keeps iterating down until it gets to a non-existant SNode.
targetNode = targetNode.getNext();//getNext is a method in my SNode that just returns a reference to that SNode's "nextNode" variable.
}
targetNode = new SNode(element);
return arrayPos;
}//end insertValue
我的问题是,在运行此方法后,它不会在所需的数组位置创建一个新节点,即使是在数组点为空时第一次运行。
如果我将targetNode = new SNode(element);
更改为array[arrayPos] = new SNode(element);
,它显然会将SNode
插入数组中,这样就可以让我相信正在发生的事情是新的{{1}正在变量SNode
下创建,但targetNode
在实例化后没有链接到数组位置。我假设它实际上是将数据从第2行的数组位置复制到变量中,但随后变成了自己独立的实体。
那么我如何targetNode
实际引用并影响targetNode
? (当我在已占用的数组空间中遍历链接的节点列表时,targetNode指向正确的节点。)
注意:为了简单起见,我遗漏了SNode
中使用setNext()
方法的行,将链接列表中的上一个节点链接到下一个节点之一。
答案 0 :(得分:1)
此处targetNode
是指array[arrayPos]
引用的对象。
SNode targetNode = array[arrayPos];//What I want to be a reference to the node at the desired position in the array
但是当你写下来的时候:
targetNode = targetNode.getNext();//getNext is a method in my SNode that just
您更改了targetNode
变量引用的对象。现在它引用它的下一个节点。
然后当你这样做:
targetNode = new SNode(element);
您创建一个新对象并将其分配给targetNode
变量,但最终它永远不会与现有节点相关联。
它不会为下一个节点分配一个新节点 要做到这一点你可以写:
targetNode.setNext(new SNode(element));
答案 1 :(得分:1)
你有一种误解。变量和数组元素都不包含对象。他们将引用保存到对象。此外,变量和数组位置本身不是对象,因此Java中没有办法引用它们。最接近的是获得变量或数组位置包含的值的副本(对象的引用)。
因此,这......
SNode targetNode = array[arrayPos];
...将array[arrayPos]
的值复制到变量targetNode
中。如果该值为非null
,则后面的变量引用数组元素所执行的相同对象,但不复制对象本身。在那种情况下,当您使用
targetNode = targetNode.getNext();
,您不想修改array[arrayPos]
或任何节点' next
引用,因为那样你就会丢失链表的元素。
但你不能两种方式。当您最终找到新SNode
的位置并执行此操作时......
targetNode = new SNode(element);
...它不会记录您最近复制SNode
的值的新targetNode
的引用。它只是将引用放在targetNode
。
您要做的是找到最后一个当前节点(如果有),并分配给它的next
引用(或者直接指向数组元素,如果它最初是null
)。
答案 2 :(得分:1)
正如其他答案所示,使用正常的解决方案,您将测试它是否是数组中的第一个元素,并在这种情况下做一些不同的事情。即如果是第一个就直接在数组中设置元素,如果不是则遍历列表。
一种有效的替代方法是在数组中使用一个虚拟元素,该元素仅用于其下一个字段,并在创建时使用虚拟元素初始化数组。在你的情况下,你甚至可以给虚拟元素一个额外的 last
字段,这将不需要遍历列表来查找最后一个元素。类似于以下内容:
interface SNodeRef {
SNode getNext();
void setNext(SNode node);
}
class FirstNode implements SNodeRef {
SNodeRef getLast();
void setLast(SNodeRef);
....
FirstNode() { setLast(this); }
}
class SNode implements SNodeRef { ... }
private int insertValue(int arrayPos, String element) {
SNode newNode = new SNode(element);
FirstNodeRef ref = array[arrayPos];
ref.getLast().setNext(newNode);
ref.setLast(newNode);
}
FirstNode[] array = new FirstNode[10];
for (int i = 0; i < array.length; i++) {
array[i] = new FirstNode();
}
或者,由于它是您使用的链表,您可以简单地使用预定义的 LinkedList
数据结构:
private int insertValue(int arrayPos, String element) {
array[arrayPos].addLast(element);
}
var array = new LinkedList<String>[10];
for (int i = 0; i < array.length; i++) {
array[i] = new LinkedList<String>();
}