简体   繁体   中英

Java - Iterating through a Linked List can't sort properly

I am attempting to iterate through a LinkedList (of Nodes, containing an Object data and a Node next) and add elements to said list, in an alphabetically sorted fashion. Here is the code snippet for this addElement method, below which I shall show the output for the whole program, and where it goes wrong.

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);
    }
}

The input for this, one at a time (and without the spaces or commas), would be: Grape, Melon, Apple, Peach, Banana

And the output would be: ( Grape ) ( Grape Melon ) ( Apple Grape Melon ) ( Apple Grape Melon Peach ) ( Apple Grape Banana Melon Peach )

As you can see, for no apparent reason (at least that I can see), everything is lexicographically sorted just fine, except for the term Banana. Why would it suddenly jump past Grape, one element ahead of where it's supposed to be? This happens with any word between Apple and Grape, such as Cherry, so I suspect there is a logic error in adding an element between the first and second terms. Help would be appreciated, as for the life of me I can't find the logic error. Cheers!

Run the debugger in your IDE and check the values of input and current being compared. Based on your code it looks like input might be something like java.lang.Object@61bbe9ba . It depends on if the element's class properly overrides the toString method. If this is the case then replace:

String input = String.valueOf(element);

with:

String input = String.valueOf(element.data);

The other possibility is that data 's toString method is evaluating to something like java.lang.Object@61bbe9ba . Either way you need to make sure that the values for input and compare being compared are correct.

Also, an easier approach to sorting would be to just use the sort method provided by Collections. Here is an example where linkedList is your LinkedList and Element is the class type of the elements of your LinkedList:

Collections.sort(linkedList, (Element element1, Element element2) -> String.valueOf(element1.data).compareTo(String.valueOf(element2.data)));

Another solution would be to create a TreeSet with the same comparator, iterate through your LinkedList and add each element to the TreeSet. The TreeSet will automatically sort itself every time you add a new element, and has the additional benefit of faster data access time than a LinkedList. TreeSet is O(log n) while a LinkedList is O(n).

Set<Element> treeSet = new TreeSet<>((Element element1, Element element2) -> String.valueOf(element1.data).compareTo(String.valueOf(element2.data)));

There was too much done, and in fact one has to both insert after a position, as also in front of one.

    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

Your code is equivalent to the following simplified version:

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);
    }
}

Now it is easier to see that the loop exits when you've either reached the end of the list or when current is greater than input . So that logic works ok.

But now look at what you are comparing input with! Initially, you're comparing it with the string value of a data field. But inside the loop, you're comparing it with the string value of iter.next() which gives you the node , not the value of data . So you are, in fact comparing the strings "Banana" with "com.example.LinkedListNode@331fe1a" . You need to use String.valueOf(iter.next().data) . (That's assuming that your LinkedListIterator behaves conventionally and iter.next() has the correct return type.)

You can make bugs like these less likely by being more strict with your data types. Specifically, you should consider making your LinkedList generic. Perhaps you haven't started studying generics yet, but when you do, you'll realise how they can make this code neater.

EDIT:

As you said iter.next() returns the actual data, then the problem must be somewhere else. The logic of the loop in your question looks ok, so I would now suspect the logic inside your LinkedListIterator class, and in particular its add method. It looks like it is adding after the next element instead of after the current element.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM