簡體   English   中英

為什么 LinkedList 不暴露其節點 class?

[英]Why does LinkedList not expose its Node class?

如果我從頭開始開發鏈表,我可以在我的業務實體 class 中存儲指向節點 object 的指針,並實現恆定的 O(1) removeinsertAfter操作。 在 java 標准庫實現中,它們是 O(n),在處理大型數據集時可能會有很大差異。

為什么他們不只是公開節點 class 並在其中封裝一些細節仍然使 class 本身(可能通過接口)可訪問? 這將使 LinkedList 更加靈活。

我們在 Apache Commons 或 Guava 中有類似FlexibleLinkedList的東西嗎?

ListIterator

為什么他們不只是公開節點 class 並在其中封裝一些細節仍然使 class 本身(可能通過接口)可訪問?

沒有必要。

為什么他們不只是公開節點 class 並在其中封裝一些細節仍然使 class 本身(可能通過接口)可訪問? 這將使 LinkedList 更加靈活。

那已經存在了。

如果您想獲得基於節點的操作的好處,例如:

  • 根據當前節點給我下一項
  • 刪除我已經擁有的節點,而不找到它
  • 在我已經擁有的節點之后插入一些東西

您只需要使用ListIterator ()返回的 ListIterator 即可。 所有List都提供此方法。

這個 class 封裝了在迭代中知道當前節點的邏輯,並提供了直接使用Node的有效操作方法,例如:

  • add - 將元素插入到next()將返回的元素之前
  • set - 將next()previous()返回的最后一個元素替換為指定元素
  • remove - 從列表中刪除next()previous()返回的最后一個元素

同時提供使用next()previous()控制迭代的方法。


例子

因此,您可以例如更改每隔一個元素:

LinkedList<Integer> values = new LinkedList<>(List.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));

int i = 0;
ListIterator<Integer> iter = values.listIterator();
while (iter.hasNext()) {
    iter.next();

    if (i % 2 == 0) {
        iter.set(100);
    }

    i++;
}

導致

[100, 2, 100, 4, 100, 6, 100, 8, 100, 10]

而且這段代碼在O(n)中運行,它不需要每次都重新定位節點。 與壞的等價物相反

for (int i = 0; i < list.size(); i++) {
    if (i % 2 == 0) {
        list.set(i, 100);
    }
}

由於您所說的原因,它在O(n^2)中運行。


隱藏Node的好處

一般來說,封裝和隱藏你的私人內部運作要好得多。 用戶不應打擾LinkedList如何在幕后完成其工作。

此外,如果它會暴露Node ,用戶可以偷偷地編輯它們,整個列表就會變得瘋狂。

例如,用戶可以這樣做

Node a = list.getNodeAtIndex(3);   
Node b = a.next;
Node c = b.next;

// Remove b
a.next = c;
c.previous = a;

無需調整列表的size 所以list.size()現在會返回一個錯誤的數字,可能會導致迭代期間崩潰。

或者你也可以引入一個危險的循環:

a.next = b;
b.next = a;

或者忘記設置previous ,導致向后迭代時不同的列表

a.next = c;
c.previous = b;

ListIterator確保此類事情不會發生,同時提供相同的功能。 因此,它不是直接向用戶公開節點,而是僅公開所需的功能,以它可以完全控制的方法的形式。

暫無
暫無

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

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