在 java compareTo 中通过多种方法进行比较?

Compare by multiple methods in java compareTo?

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

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

如果要覆盖 compareTo,则不必使用 getter 或 setter。您也可以放弃 else/return 语句,因为它们是终端 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);
}

您可以通过以下方式为您的学生 class 创建比较器:

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

我认为你的代码是正确的。

What would be the most effective way to sort a data structure in this hierarchy?

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

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

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

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

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

我个人会使用 编写此代码,但如果此代码用于作业,则可能不是他们所期望的。