簡體   English   中英

解碼LinkedList實現

[英]Decoding LinkedList implementation

只是為了理解實現,操作等,我從JDK復制了LinkedList類,並以非泛型(String only)的方式進行了修改。 你可以在這里找到實際的代碼。 這個問題與此問題有關
addlast僅()

public void addLast(String e){
    System.out.println("Invoked:addLast()");
    linkLast(e);
}

節點內部類

private static class Node {
     String item;
     Node next;
     Node prev;
     Node(Node prev, String element, Node next) {
         this.item = element;
         this.next = next;
         this.prev = prev;
    }
    @Override   public String toString() {
        return "Node [item=" + item + ", next=" + next + ", prev=" + prev+ "]";
    }
}

linkLast()

void linkLast(String e) {
    System.out.println("Invoked:linkLast(" + e + ")");
    final Node l = last;
    final Node newNode = new Node(l, e, null);
    System.out.println("\tCreatd new node as:" + newNode);
    last = newNode;
    System.out.println("\tSetting this node as last");
    if (l == null){
        // Applicable for 1st node. Last & First point to newNode
        first = newNode;
        System.out.println("\tLast was null, setting this node as first.");
    }          
    else{
        // Set newNode as next of previous Last.
        System.out.println("\tLast was not null, seting this node as next node of previous Last.");
        l.next = newNode;
    }
    size++;
    //System.out.println("Size of list:" + size);
    modCount++;
    System.out.println("\tMod Count:" + modCount + "\n");
}

我得到一個stackoverflow錯誤,當我執行這個類時,

public static void main(String args[]){
    LinkedListDemo obj = new LinkedListDemo();
    obj.add("B");
    obj.addFirst("A");
    obj.addLast("C");
}

產量

Invoked:add(B)
Invoked:linkLast(B)
    Creatd new node as:Node [item=B, next=null, prev=null]
    Setting this node as last   Last was null, setting this node as first.
    Mod Count:1
Invoked:addFirst()
Invoked:linkFirst(A)
    Creatd new node asNode [item=A, next=Node [item=B, next=null, prev=null], prev=null]
    Seting this node as first
    First was not null, seting this node as next node of previous First.
    Mod Count:2
Invoked:addLast()
Invoked:linkLast(C)
Exception in thread "main" java.lang.StackOverflowError
    at java.lang.String.getChars(String.java:826)
    at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:416)at java.lang.StringBuilder.append(StringBuilder.java:132)
    at java.lang.StringBuilder.<init>(StringBuilder.java:110)
    at collections.LinkedListDemo$Node.toString(LinkedListDemo.java:570)
    at java.lang.String.valueOf(String.java:2847)
    at java.lang.StringBuilder.append(StringBuilder.java:128)
    at collections.LinkedListDemo$Node.toString(LinkedListDemo.java:570)

然后最后3行不斷重復。 我無法弄清楚造成這種情況的原因。

更新 - 基於收到的回復
所以,如果理解是正確的,

Invoked:add(A)
Invoked:linkLast(A)
    Creatd new node as:Node [item=A, next=null, prev=null]
    Setting this node as last
    Last was null, setting this node as first.
    Mod Count:1
Invoked:add(B)
Invoked:linkLast(B)
    Creatd new node as:Node [item=B, next=null, prev=Node [item=A, next=null, prev=null]]
    Setting this node as last
    Last was not null, seting this node as next node of previous Last.
    Mod Count:2

在,此階段“節點B”僅使用單向鏈接(prev)創建,其中調用toString()。 只有在其他側鏈接(下一個)被鏈接之后。 並且這個雙鏈接是下次插入時無限遞歸的原因。

也許這就是為什么toString()方法既沒有在它的兩個超類AbstractSequentialList,AbstractList中實現,也沒有在AbstractCollection中實現的原因。 該實現提取Iterator,迭代打印colletcion。

那么,為什么它只在第3次插入時發生。 兩次插入不會導致此問題。

問題是你的toString方法,它在嘗試打印prevnext節點時遞歸調用。

如果當前打印的Node next不為null, next.toString()調用next.toString() ,並且當打印該Nodeprev時,再次調用原始Node toString() ,因此遞歸沒有結束。

可能的方法:

@Override
public String toString() 
{
    return "Node [item=" + item + ", next=" + (next==null?"null":next.item) + ", prev=" + (prev==null?"null":prev.item) + "]";
}

關於意見:

添加第一個節點后,列表如下所示:

prev             next
null <- Node1 -> null

firstlast都指向Node1

toString中沒有無限遞歸的風險。

添加第二個節點后,列表如下所示:

null <- Node1 -> <- Node2 -> null

first指的是Node1, last指的是Node2

如您所見,Node1和Node2相互引用(Node1是Node2的prev ,Node2是Node1的next )。 因此,嘗試在第二次插入后使用原始的toString()方法打印其中一個節點將導致無限遞歸。

但是,由於您在行l.next = newNode;之前打印新節點l.next = newNode; 執行后,您不會在第二次插入時獲得無限遞歸,僅在第三次插入中。 如果移動System.out.println("\\tCreatd new node as:" + newNode); linkLast的末尾,第二次插入將導致無限遞歸。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM