[英]Java - Iterating through a Linked List can't sort properly
我試圖遍歷 LinkedList(節點,包含一個對象數據和一個節點),並以字母順序排序的方式將元素添加到所述列表中。 下面是這個 addElement 方法的代碼片段,下面我將顯示整個程序的輸出,以及出錯的地方。
public void addElement(Object element) {
LinkedListIterator iter = new LinkedListIterator();
if (first == null) {
addFirst(element); // If list is empty, make the input first
} else {
String input = String.valueOf(element);
String current = String.valueOf(first.data);
int compare = input.compareTo(current);
while (iter.hasNext()) {
if (compare > 0) { // element is greater than position
// Do nothing, keep going
} else if (compare < 0) { // element is where it needs to be
// Since element is now smaller than the next thing,
// break the loop to add it.
break;
} else { // element completely matches position
// Do nothing, keep going
}
current = String.valueOf(iter.next());
compare = input.compareTo(current);
}
iter.add(element);
}
}
一次輸入一個(沒有空格或逗號),將是:Grape、Melon、Apple、Peach、Banana
輸出將是:(葡萄)(葡萄瓜)(蘋果葡萄瓜)(蘋果葡萄瓜桃)(蘋果葡萄香蕉瓜桃)
正如您所看到的,沒有明顯的原因(至少我可以看到),除了術語 Banana 之外,所有內容都按字典順序排列得很好。 為什么它會突然跳過葡萄,比它應該在的位置提前一個元素? Apple 和 Grape 之間的任何單詞都會發生這種情況,例如 Cherry,因此我懷疑在第一項和第二項之間添加元素時存在邏輯錯誤。 幫助將不勝感激,至於我的生活,我找不到邏輯錯誤。 干杯!
在您的 IDE 中運行調試器並檢查正在比較的input
和current
的值。 根據您的代碼, input
可能類似於java.lang.Object@61bbe9ba
。 這取決於元素的類是否正確覆蓋了toString
方法。 如果是這種情況,則更換:
String input = String.valueOf(element);
與:
String input = String.valueOf(element.data);
另一種可能性是data
的toString
方法正在評估類似java.lang.Object@61bbe9ba
東西。 無論哪種方式,您都需要確保被比較的input
和compare
的值是正確的。
此外,一種更簡單的排序方法是使用 Collections 提供的排序方法。 這是一個示例,其中linkedList
是您的 LinkedList,而Element
是您的 LinkedList Element
的類類型:
Collections.sort(linkedList, (Element element1, Element element2) -> String.valueOf(element1.data).compareTo(String.valueOf(element2.data)));
另一種解決方案是使用相同的比較器創建一個 TreeSet,遍歷 LinkedList 並將每個元素添加到 TreeSet。 每次添加新元素時,TreeSet 都會自動對其進行排序,並且具有比 LinkedList 更快的數據訪問時間的額外好處。 TreeSet 是 O(log n) 而 LinkedList 是 O(n)。
Set<Element> treeSet = new TreeSet<>((Element element1, Element element2) -> String.valueOf(element1.data).compareTo(String.valueOf(element2.data)));
做的太多了,事實上一個人必須在一個位置之后插入,在一個位置之前也插入。
String sought = String.valueOf(element);
while (iter.hasNext()) {
current = String.valueOf(iter.next());
comparison = sought.compareTo(current);
if (comparison == 0) {
return; // Already added
} else if (compare > 0) {
// Sought element is larger than the current element,
// so add it in front
iter.previous();
break;
}
}
iter.add(element); // Add it after this one
您的代碼等效於以下簡化版本:
public void addElement(Object element) {
if (first == null) {
addFirst(element); // If list is empty, make the input first
} else {
String input = String.valueOf(element);
LinkedListIterator iter = new LinkedListIterator();
String current = String.valueOf(first.data);
while (iter.hasNext() && input.compareTo(current) >= 0) {
current = String.valueOf(iter.next());
}
iter.add(element);
}
}
現在,當您到達列表末尾或current
大於input
時,更容易看到循環退出。 所以這個邏輯可以正常工作。
但是現在看看您正在將input
與什么進行比較! 最初,您將它與data
字段的字符串值進行比較。 但是在循環內部,您將它與iter.next()
的字符串值進行比較,它為您提供node ,而不是data
的值。 所以你實際上是在比較字符串"Banana"
和"com.example.LinkedListNode@331fe1a"
。 您需要使用String.valueOf(iter.next().data)
。 (假設您的LinkedListIterator
行為符合常規並且iter.next()
具有正確的返回類型。)
您可以通過對數據類型更加嚴格來減少此類錯誤的發生。 具體來說,您應該考慮使您的LinkedList
通用。 也許您還沒有開始學習泛型,但是當您開始學習時,您會意識到它們如何使代碼更簡潔。
編輯:
正如您所說的iter.next()
返回實際數據,那么問題一定出在其他地方。 您問題中的循環邏輯看起來沒問題,所以我現在懷疑您的LinkedListIterator
類內部的邏輯,特別是它的add
方法。 看起來它是在下一個元素之后而不是在當前元素之后添加。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.