【问题标题】:Compare by multiple methods in java compareTo? [duplicate]在java compareTo中通过多种方法进行比较? [复制]
【发布时间】:2020-05-07 17:12:57
【问题描述】:

我认为这不是描述该标题的最佳方式,但我想不出更好的方式来描述它。这是我的问题:我必须编写一个以几种不同方式进行比较的方法。如果姓氏相同,则需要按名字进行比较。如果名字相同,那么我需要按部分排序。在这个层次结构中对数据结构进行排序的最有效方法是什么?这是我目前所拥有的,我想我明白为什么它不起作用但我想不出另一种方法来编写这个函数:

//Student class structure, each field has a public get/set method
public class Student implements Comparable<Student>
{
  private String fname;
  private String lname;
  private int section;
}

//My current compareTo method
@Override
public int compareTo(Student s)
{
  /*
    -compare by last name
    -if the same, compare by first name
    -if the same, compare by section
  */

  String slast = s.getLastName();

  if(lname.compareTo(slast) == 0)
  {
    String sfirst = s.getFirstName();

    if(fname.compareTo(sfirst) == 0)
    {
      int sclass = s.getSection();

      return Integer.compare(section, sclass);
    }

    else
    {
      return fname.compareTo(sfirst);
    }
  }

  else
  {
    return lname.compareTo(slast);
  }
}

【问题讨论】:

  • 它是否有效并且您正在寻找更好的方法来执行此操作,或者您对此代码有任何问题?如果是后者,请添加更多详细信息,说明哪些输入未能给出预期结果
  • 这能回答你的问题吗? How to compare objects by multiple fields
  • @user7 我的错误,我的代码问题出在我没想到会出现的问题中,删除问题,我的错。
  • @Scratte 确实有帮助,谢谢

标签: java compareto


【解决方案1】:

您可以通过这种方式为您的学生类创建一个比较器:

Comparator<Student> comparator = Comparator
        .comparing(Student::getLastName)
        .thenComparing(Student::getFirstName)
        .thenComparing(Student::getSection);

然后使用这个比较器(而不是实现 Comparable 接口)用 Student 对象对列表进行排序,或者用这些对象创建一个 TreeMap:

Collections.sort(listOfStudents, comparator);
TreeMap<Student> mapOfStudents = new TreeMap<>(comparator);

【讨论】:

    【解决方案2】:

    如果要覆盖 compareTo,则不必使用 getter 或 setter。您也可以放弃 else/return 语句,因为它们是终端返回语句,而只需使用 return。

    @Override
    public int compareTo(Student s) {
        if (lname.compareTo(s.lname) == 0) {
            if (fname.compareTo(s.fname) == 0) {
                return section.compareTo(s.section);
            }
            return fname.compareTo(s.fname);
        }
        return lname.compareTo(s.lname);
    }
    

    【讨论】:

      【解决方案3】:

      您的代码在我看来是正确的。

      在此对数据结构进行排序的最有效方法是什么 层次结构?

      嗯,值得一提的是,您可能会多次进行前两次比较(名字和姓氏)

      if(lname.compareTo(slast) == 0)
      {
          //...
      }
      else
      {
          return lname.compareTo(slast);
      }
      

      你应该很明显地做了两次lname.compareTo(slast)。您可以将结果存储在变量中。

      int lastNameComparison = lname.compareTo(slast);
      if(lastNameComparison == 0)
      {
          //...
      }
      else
      {
          return lastNameComparison;
      }
      

      这是风格问题,但我不会费心将 getter 的结果存储到变量中。只需在需要时给他们打电话。

      结合以上两点,你得到:

      int lastNameComparison = lname.compareTo(s.getLastName();
      if (lastNameComparison == 0)
      {
          int firstNameComparison = fname.compareTo(s.getFirstName());
          if (firstNameComparison == 0)
          {
              return Integer.compare(section, s.getSection());
          }
          else
          {
              return firstNameComparison;
          }
      }
      else
      {
          return lastNameComparison;
      }
      

      嵌套非常丑陋,如果我们需要添加另一个条件,它会变得更糟。

      我们可以通过反转条件并使用多个返回语句来解决这个问题。

      int lastNameComparison = lname.compareTo(s.getLastName());
      if (lastNameComparison != 0) return lastNameComparison;
      
      // Last names must be equal
      int firstNameComparison = fname.compareTo(s.getFirstName());
      if (firstNameComparison != 0) return firstNameComparison;
      
      // First names must be equal
      return Integer.compare(section, s.getSection());
      

      我个人会使用declarative style 来编写此代码,但如果此代码用于分配,那可能不是他们所期望的。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-10-22
        • 2021-08-12
        • 1970-01-01
        • 1970-01-01
        • 2015-09-06
        相关资源
        最近更新 更多