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