我正在尝试遍历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);
}
}
此输入,一次一个(没有空格或逗号),将是: 葡萄, 甜瓜, 苹果, 桃子, 香蕉
输出将是: ( 葡萄 ) ( 葡萄瓜 ) (苹果葡萄瓜) (苹果葡萄甜瓜桃) (苹果葡萄香蕉瓜桃)
如您所见,没有明显的原因(至少我可以看到),除了术语 Banana 之外,所有内容都按字典顺序排序得很好。为什么它会突然跳过葡萄,比它应该在的地方领先一个元素?苹果和葡萄之间的任何单词都会发生这种情况,例如樱桃,所以我怀疑在第一项和第二项之间添加元素存在逻辑错误。帮助将不胜感激,至于我的生活,我找不到逻辑错误。干杯!
在 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
的值是正确的。
此外,更简单的排序方法是仅使用集合提供的排序方法。下面是一个示例,其中linkedList
是您的 LinkedList,Element
是 LinkedList 元素的类类型:
Collections.sort(linkedList, (Element element1, Element element2) -> String.valueOf(element1.data).compareTo(String.valueOf(element2.data)));
另一种解决方案是使用相同的比较器创建一个树集,遍历您的 LinkedList 并将每个元素添加到树集中。每次添加新元素时,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()
的字符串值进行比较,该字符串值为您提供节点,而不是data
的值。所以你实际上是在比较字符串"Banana"
与"com.example.LinkedListNode@331fe1a"
.您需要使用String.valueOf(iter.next().data)
.(这是假设您的LinkedListIterator
行为正常,并且iter.next()
具有正确的返回类型。
您可以通过更严格地使用数据类型来降低此类错误的可能性。具体来说,您应该考虑将LinkedList
设为通用。也许你还没有开始研究泛型,但是当你开始研究泛型时,你会意识到它们如何使这段代码更整洁。
编辑:
正如您所说iter.next()
返回实际数据,那么问题一定出在其他地方。您问题中的循环逻辑看起来不错,所以我现在怀疑您的LinkedListIterator
类中的逻辑,尤其是其add
方法。看起来它是在下一个元素之后添加的,而不是在当前元素之后添加的。