【问题标题】:Java - Issue with Collections.sort()Java - Collections.sort() 的问题
【发布时间】:2015-08-05 02:04:11
【问题描述】:

我目前正在编写一个打印书籍 ArrayList 的程序。 book 元素的每个 ArrayList 都由一个字符串(书名)和一个 ArrayList(该书的作者)组成。我需要对我的 ArrayList 书籍进行排序,以便它们按字母顺序显示(按标题排序)。我的问题是,当我打印新的 ArrayList(我调用 Collections.sort() 的列表)时,我得到的输出与我第一次打印非排序版本时相同。

我从我的驱动程序调用myLib.sort();,该驱动程序转到我的库类中的这个方法:

   public void sort()
   {
      Collections.sort(myBooks);
   }

myBooks 是我前面提到的书籍的 ArrayList。根据我的阅读,Collections.sort("ArrayList name") 应该按字母顺序对我的列表进行排序。如果这是不正确的,我需要使用compareTo()equals() 方法,那么这里是出现在class Book 中的那些方法,我用来构建进入我的class Library 的书籍:

   public int compareTo(final Book theOther)
   {
      int result = 0;
      if (myTitle.equals(theOther.myTitle))
      {
         if (myAuthors.get(0) != theOther.myAuthors.get(0))
         {
            result = 1;
         }
      }
      else
      {
         result = 0;
      }
      return result;
   }
   public boolean equals(final Object theOther)
   {

      if (theOther instanceof String)
      {
         String other = (String) theOther;
         return myTitle == other;
      }
      else
      {
         return false;
      }  
   }

我能想到的唯一剩下的可能问题是我的打印方法。我的驱动程序打印 myLib 这是一个库。我的图书馆类有以下toString() 方法:

   public String toString()
   {
      String result = "";
      for (int i = 0; i < myBooks.size(); i++)
      {

         String tempTitle = myBooks.get(i).getTitle();
         ArrayList<String> tempAuthors = myBooks.get(i).getAuthors();
         Book tempBook = new Book(tempTitle, tempAuthors);
         result += (tempBook + "\n");
      }
      return result;
   }

这会从我的 Book 类 toString() 方法中获取每本书和该书的字符串,如下所示:

   public String toString()
   {
      return "\"" + myTitle + ",\" by " + myAuthors;
   }

如果这太少、太多、太混乱、不够清楚等等......请在评论中告诉我,我会尽快编辑帖子。如果需要,我还可以发布我的三个课程的全部内容。我是 Java 新手,而且在发帖方面也很新,所以我仍然习惯于两种情况下的工作方式,所以如果你对我放轻松,我将不胜感激。谢谢!

【问题讨论】:

  • 尝试将“return 0”改为“-1”,
  • @BachT 当我这样做时,我的程序会为我的每本书打印诸如 Book@5c647e05 之类的内容。
  • public int compareTo(final Book theOther) { int result = myTitle.compareTo(theOther.myTitle); if (result == 0) { if (myAuthors.get(0) != theOther.myAuthors.get(0)) { result = 0; } } 返回结果; }
  • 试试看是否有效?
  • @BachT 我应该编辑我的帖子并添加所有代码,还是在与您的私人聊天中这样做会更好?

标签: java sorting arraylist collections tostring


【解决方案1】:

您的 compareTo() 方法似乎有误,请注意 Collections.sort() 使用该方法来比较列表中的对象。

您只检查标题是否相等,如果相等则比较第一作者,如果相等则返回 1,否则返回 0;

compareTo() 用于检查该对象是否小于等于大于比您要比较的对象(返回 0是等于,负数表示较小,正数表示较大,您返回正数或 0)。我建议您阅读 compareTo() 方法的 javadoc。

这里以Book 类的实现为例,我只根据标题进行比较(我省略了作者列表的比较)。

public class Book implements Comparable<Book> {
    private String title;
    private List<String> authors;

    public Book(String title) {
        this.title = title;
    }

    public int compareTo(Book o) {
        return this.title.compareTo(o.title);
    }

    @Override
    public boolean equals(Object b){
        if(!(b instanceof Book)){
            return false;
        }
        //authors comparison omitted
        return this.title.equals(((Book) b).title);
    }

    @Override
    public String toString(){
        return "Title: "+ title; //todo: add authors also if need
    }     
}

正如您在 Book.compareTo() 方法中看到的,我依赖 String.compareTo()。 它将返回 -1、0 或 1;如果您需要根据作者列表进行比较,您还必须考虑方法的逻辑并考虑一些问题:

  • 如果仅依赖列表中的第一作者就足够了
  • 如果您需要确保作者列表已排序
  • 如果作者列表为空会发生什么情况

另外注意compareTo 应该与 equals 一致,这意味着如果 compareTo 返回 0,则 equals 应该返回 true,反之亦然。

【讨论】:

    【解决方案2】:

    根据documentation,你也应该返回负值:

    返回负整数、零或正整数,因为此对象小于 大于、等于或大于指定的对象。

    public int compareTo(final Book theOther) {
        int result = myTitle.compareTo(theOther.myTitle);
        if (result == 0) {
            result = myAuthors.get(0).compareTo(theOther.myAuthors.get(0));
        }
        return result;
    }
    

    检查@flowryn以获得更好的答案,因为他还根据documentation提到了equals()

    强烈建议,但并非严格要求 (x.compareTo(y)==0) == (x.equals(y))。一般来说,任何类 实现 Comparable 接口并违反此条件 应该清楚地表明这一事实。推荐的语言是“注意: 此类具有与 equals 不一致的自然顺序。”

    【讨论】:

    • 不完整,注意@Trafton 不保证 equal 和 compareTo 的一致性,这可能会导致一些意外的行为
    • 是的,您对一致性的看法是正确的。但我认为,对于排序的问题,像OP一样,我们只需要实现Comparable,所以唯一需要实现的方法是compareTo()equals() 将用于其他操作。
    • 查看您链接到的文档:强烈建议但不严格要求 (x.compareTo(y)==0) == (x.equals(y))
    • 是的,我同意你的看法:我们应该有equals() 否则其他人会搞砸的。但是(我认为)对于这种情况,不是严格要求
    • 如果你不干扰其他收藏就可以了。
    猜你喜欢
    • 2015-01-18
    • 1970-01-01
    • 1970-01-01
    • 2010-10-31
    • 2013-02-11
    • 1970-01-01
    • 2011-02-22
    • 1970-01-01
    • 2018-10-11
    相关资源
    最近更新 更多