【问题标题】:compareTo() method is not overriding default method when using Comparable interface使用 Comparable 接口时 compareTo() 方法不会覆盖默认方法
【发布时间】:2012-02-04 13:23:59
【问题描述】:

我正在尝试通过编写自己的方法并使用可比较的实现来覆盖 java 中的默认 compareTo() 方法,但似乎 java 仍在使用默认方法。

我正在尝试按从 .dat 文件获得的长度对字符串数组进行排序,但是它一直按字母顺序对其进行排序。如果有人能告诉我我做错了什么,我将不胜感激,因为我无法弄清楚为什么这不起作用。

谢谢

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

这是包含main方法的类

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

【问题讨论】:

    标签: java interface comparable compareto


    【解决方案1】:

    帮自己一个忙:每次重写方法时,添加@Override 注释。如果您在覆盖该方法时出错,这将给您一个编译错误,这就是这里发生的事情。你正在实现它错误,因为ComparableComparable&lt;T&gt; 的“原始”形式没有声明方法compareTo(String),它声明了一个方法compareTo(Object)

    要使其按原样编译,您需要接受Object 而不是String 或实现Comparable&lt;String&gt; 而不是Comparable

    但这在大多数情况下确实是不正确的,因为这样的比较不是对称的:您可以将 Word 与 String 进行比较,但不能将 String 与单词进行比较。

    您很可能希望实现Comparable&lt;Word&gt; 而不是Comparable 并接受WordcompareTo()

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

    请注意,尽管Comparable 仅在类型是本质上 排序(文档称为“自然顺序”)(如日期或数字)时才真正适合。由于您实际上并没有按字母顺序比较两个单词(这将最接近字符串的自然顺序),因此这是使用 外部比较器 的更好选择。

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

    【讨论】:

      【解决方案2】:

      Comparable 已输入,但您使用的是原始类型。试试这个:

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

      【讨论】:

      • 这仍然不能解决 sortByLength 方法正在排序字符串列表,而不是 Word 对象列表的事实。
      • 我做了这些更改,它编译得很好(就像以前一样),但它仍然按字母顺序对数组进行排序。
      【解决方案3】:

      检查 compareTo 方法 here 的签名

      应该是int compareTo(Object o)

      你给public int compareTo(String rhs)

      你也可以在你的方法中添加@Override注解。如果您没有遵循正确的签名,它会通知您。

      【讨论】:

      • 您的链接指向 Java 1.4 文档,这些文档是在将泛型添加到语言中之前编写的。如果您查看docs.oracle.com/javase/6/docs/api/java/lang/Comparable.html 的Java 6 文档,您将看到实现Comparable&lt;String&gt; 的类中compareTo 方法的正确签名确实是public int compareTo(String rhs)。也就是说,发布的代码实现了原始的Comparable,而不是Comparable&lt;String&gt;,这是不受欢迎的。
      【解决方案4】:

      简短版:您需要改用Arrays.sort method taking a Comparator

      长版:一行

      Arrays.sort(array);
      

      sortByLength 方法中不断调用它正在排序的对象的compareTo 方法——这些对象是字符串!相反,你需要这条线

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

      或者您可以创建一个实现Comparator&lt;String&gt; 的单独类,并将其实例用作Arrays.sort 的第二个参数。

      【讨论】:

      • 哇,我对它与类中其他代码的上下文完全吻合的地方感到困惑。我敢肯定,如果我把所有的都放在一行上面写着:Arrays.sort(array);
      • 为什么不呢?这是一个匿名类的例子,你可以在en.wikibooks.org/wiki/Java_Programming/…找到一个匿名类的例子@
      • 好吧,我试着复制你写的东西来代替 Arrays.sort(array);它给了我 43 个错误。
      猜你喜欢
      • 1970-01-01
      • 2017-02-02
      • 2015-11-27
      • 1970-01-01
      • 2023-03-21
      • 1970-01-01
      • 2011-08-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多