4

I am trying to overwrite the default compareTo() method in java by writing my own and using implements comparable, however it seems that java is still using the default method.

I am trying to sort an array of Strings by length that I get from a .dat file, however it keeps sorting it by alphabetic order instead. I would appreciate it if someone could tell me what I am doing wrong as I cannot figure out why this does not work.

Thanks

import static java.lang.System.*;
import java.util.Arrays;

public class Word implements Comparable
{
private String word;
private String[] array;

public Word()
{
    word = "";
}

public Word(String s)
{
    word = s;
}

public void setWord(String s)
{
    word = s;
}

public int compareTo(String rhs)
{
    String temp = (String)rhs;
    if(word.length() > temp.length())
        return 1;
    else if(word.length() < temp.length())
        return -1;

    return 0;
}

public void setSize(int size)
{
    array = new String[size];
}

public void add(int spot, String other)
{
    array[spot] = other;
}

public String[] sortByLength()
{
    Arrays.sort(array);
    return array;
}
public String toString()
{
    return Arrays.toString(array);
}
}

Here is the class that contains the main method

import java.io.File;
import java.io.IOException;
import java.util.Scanner;
import java.util.Arrays;
import static java.lang.System.*;

public class Lab18d
{
public static void main( String args[] ) throws IOException
{
    Scanner file = new Scanner(new File("lab18d.dat"));

    int size = file.nextInt();
    file.nextLine();
    Word test = new Word();
    test.setSize(size);
    String word = "";

    for(int i = 0; i < size; i++)
    {
        word = file.next();
        test.setWord(word);
        test.add(i, word);
    }
    test.sortByLength();
    System.out.println(test);
}
}
seh
  • 14,999
  • 2
  • 48
  • 58
Special K
  • 41
  • 1
  • 1
  • 2

4 Answers4

4

Do yourself a favour: every time you override a method, add the @Override annotation to it. This will give you a compile error if you make a mistake in overriding the method, which is what is happening here. You are implementing it wrong, as Comparable (the "raw" form of Comparable<T> does not declare a method compareTo(String), it declares a method compareTo(Object).

To get it to compile as is, you would need to accept an Object instead of a String or implement Comparable<String> instead of Comparable.

But that would really be incorrect in most cases, because such a comparison is not symmetric: you can compare a Word to a String but not a String to a word.

Most likely you want to implement Comparable<Word> instead of Comparable and accept a Word to compareTo().

@Override
public int compareTo(Word other)
{
    String temp = other.word;
    //...
}

Note though that Comparable is only a really good fit when a type is intrinsically ordered (what the docs call a "natural order") like dates or numbers. Since you are not actually comparing the two words alphabetically (which would be the closest to a String's natural order) this is a better candidate for using an external comparator.

//since Word.word is a private member, this either needs to be nested inside of Word
//or Word.word would need to be given an accessor method
public static class LengthComparator implements Comparator<Word> {
    @Override
    public int compare(Word word1, Word word2) {
        return Integer.valueOf(word1.word.length()).compareTo(word2.word.length());
    }
}
Mark Peters
  • 80,126
  • 17
  • 159
  • 190
2

Comparable is typed, but you're using the raw type. Try this:

public class Word implements Comparable<Word> { // Note: typing of Comparable
    ...

    public int compareTo(Word rhs) { // Note: parameter is typed
        String temp = rhs.word;
        return word.length() - temp.length(); // Note: Simplification of code
    }
}
Bohemian
  • 412,405
  • 93
  • 575
  • 722
  • This still doesn't fix the fact that the `sortByLength` method is sorting a list of strings, not a list of `Word` objects. – Adam Mihalcin Feb 04 '12 at 04:28
  • I made those changes and it compiles fine (as it did before), but it is still sorting the array alphabetically. – Special K Feb 04 '12 at 04:39
1

Check the signature of compareTo method here

It should be int compareTo(Object o)

and you are giving public int compareTo(String rhs)

You can also add @Override annotation to your method. It will let you know if you are not following proper signature.

gprathour
  • 14,813
  • 5
  • 66
  • 90
  • Your link points to Java 1.4 docs, which were written before generics were added to the language. If you check the Java 6 docs at http://docs.oracle.com/javase/6/docs/api/java/lang/Comparable.html, you will see that the correct signature of the `compareTo` method in a class implementing `Comparable` is indeed `public int compareTo(String rhs)`. That said, the posted code implements raw `Comparable` rather than `Comparable`, which is frowned upon. – Adam Mihalcin Feb 04 '12 at 04:23
0

The short version: You need to use the Arrays.sort method taking a Comparator instead.

The long version: The line

Arrays.sort(array);

in the sortByLength method keeps calling the compareTo methods on the objects it's sorting - and those objects are strings! Instead, you need the line

Arrays.sort(array, new Comparator<String>() {
    @Override
    public int compare(String s1, String s2) {
        if (s1.length() > s2.length())
            return 1;
        if (s1.length() < s2.length())
            return -1;

        return 0;
    }
});

or you can create a separate class implementing Comparator<String> and use an instance of that as the second argument to Arrays.sort.

Adam Mihalcin
  • 14,242
  • 4
  • 36
  • 52
  • Woah, I'm confused on where that exactly fits in with the context of the other code in the class. I'm pretty sure that won't work if I put all of the in place of the one line that says: Arrays.sort(array); – Special K Feb 04 '12 at 04:45
  • Why not? It's an example of an anonymous class, and you can find an example of an anonymous class at http://en.wikibooks.org/wiki/Java_Programming/Nested_Classes#Anonymous_Classes – Adam Mihalcin Feb 04 '12 at 04:47
  • Well, I tried copying what you wrote in place of the Arrays.sort(array); and it gave me 43 errors. – Special K Feb 04 '12 at 04:55