如何按多个字段比较对象


237

假设您有一些对象,这些对象具有可以通过以下方式比较的多个字段:

public class Person {

    private String firstName;
    private String lastName;
    private String age;

    /* Constructors */

    /* Methods */

}

因此,在此示例中,当您询问是否:

a.compareTo(b) > 0

您可能会问a的姓氏是否早于b的姓氏,或者a是否早于b,等等。

在这些对象之间进行多重比较而不增加不必要的混乱或开销的最干净的方法是什么?

  • java.lang.Comparable 界面仅允许一个字段进行比较
  • 在我看来compareByFirstName(),添加许多比较方法(即,compareByAge()等)比较混乱。

那么最好的方法是什么呢?


3
为什么这是CW?这是一个完全有效的编程问题。
Elie

2
您是否知道Comparable允许按您希望的多个字段进行比较?
DJClayworth

Answers:


81

您可以实现Comparator比较两个Person对象的,并且可以根据需要检查任意多个字段。您可以在比较器中放入一个变量,以告知要与哪个字段进行比较,尽管编写多个比较器可能会更简单。


5
我实际上更喜欢使用单个比较器的想法。我认为这个答案没有错,但是任何阅读它的人都应该检查下面的史蒂夫·郭答案。
FelipeLeão2014年

仅当您需要不同的比较方法而不是数据本身的功能时,才使用多个比较器。例如,有时您要按名称进行比较,其他时间按年龄进行比较,等等。要同时按多个字段进行比较,只能使用一个比较器将是必要的。
Elie

399

使用Java 8:

Comparator.comparing((Person p)->p.firstName)
          .thenComparing(p->p.lastName)
          .thenComparingInt(p->p.age);

如果您有访问器方法:

Comparator.comparing(Person::getFirstName)
          .thenComparing(Person::getLastName)
          .thenComparingInt(Person::getAge);

如果一个类实现Comparable,则可以在compareTo方法中使用这样的比较器:

@Override
public int compareTo(Person o){
    return Comparator.comparing(Person::getFirstName)
              .thenComparing(Person::getLastName)
              .thenComparingInt(Person::getAge)
              .compare(this, o);
}

5
尤其(Person p)对于强制比较器而言,强制转换很重要。
–membersound

5
比较大量对象(例如排序)时,效率如何?是否必须Comparator在每个调用中创建新实例?
jjurm

4
当我比较的字段之一为null(例如String)时,出现NullPointerException。无论如何,是否要保留此比较格式,但允许它为null安全?
rveach

3
@jjurm- .thenComparing(Person::getLastName, Comparator.nullsFirst(Comparator.naturalOrder()))第一个字段选择器,然后是比较器
Givenkoa

2
每次调用该方法时,都会在创建@jjurm时使用compareTo如上所示的@jjurm Comparator。您可以通过将比较器存储在私有static final字段中来防止这种情况。
甘道夫

165

您应该实施Comparable <Person>。假设所有字段都不为空(为简单起见),age是一个int,而compare排名是first,last,age,则compareTo方法非常简单:

public int compareTo(Person other) {
    int i = firstName.compareTo(other.firstName);
    if (i != 0) return i;

    i = lastName.compareTo(other.lastName);
    if (i != 0) return i;

    return Integer.compare(age, other.age);
}

10
如果实现Comparable <Person>,则该方法为compareTo(Person p)..看来此答案与Comparator的compare <T o1,T o2>方法混合使用了
Mike

5
不建议这样做。有多个字段时,请使用“比较器”。
indika 2014年

1
这是目前最好的解决方案,(比更多的比较器要好)
Vasile Surdu 2014年

4
@indika,我很好奇:为什么不建议这样做?比较使用多个属性对我来说似乎完全可以。
ARS-姜黄-VITA-杆菌

4
@ ars-longa-vita-brevis,如果您使用Comparable,则排序逻辑必须在要对其对象进行排序的同一类中,因此这被称为对象的自然排序。通过使用Comparator,您可以在Person类之外编写自定义排序逻辑。如果只想按其名字或姓氏比较Person对象,则不能使用此逻辑。您必须再次编写,
indika

78

(从多种方式对Java对象列表进行排序的方式

要点中的工作代码

使用Java 8 lambda(2019年4月10日添加)

Java 8通过lambda很好地解决了这个问题(尽管Guava和Apache Commons可能仍然提供更大的灵活性):

Collections.sort(reportList, Comparator.comparing(Report::getReportKey)
            .thenComparing(Report::getStudentNumber)
            .thenComparing(Report::getSchool));

感谢下面的 @gaoagong的回答

凌乱而令人费解:手工排序

Collections.sort(pizzas, new Comparator<Pizza>() {  
    @Override  
    public int compare(Pizza p1, Pizza p2) {  
        int sizeCmp = p1.size.compareTo(p2.size);  
        if (sizeCmp != 0) {  
            return sizeCmp;  
        }  
        int nrOfToppingsCmp = p1.nrOfToppings.compareTo(p2.nrOfToppings);  
        if (nrOfToppingsCmp != 0) {  
            return nrOfToppingsCmp;  
        }  
        return p1.name.compareTo(p2.name);  
    }  
});  

这需要大量的输入,维护并且容易出错。

反射方式:使用BeanComparator排序

ComparatorChain chain = new ComparatorChain(Arrays.asList(
   new BeanComparator("size"), 
   new BeanComparator("nrOfToppings"), 
   new BeanComparator("name")));

Collections.sort(pizzas, chain);  

显然,这更加简洁,但是当您通过使用字符串(没有类型安全性,自动重构)而失去对字段的直接引用时,更容易出错。现在,如果重命名了字段,则编译器甚至不会报告问题。此外,由于此解决方案使用反射,因此排序速度要慢得多。

到达那里:使用Google Guava的ComparisonChain进行排序

Collections.sort(pizzas, new Comparator<Pizza>() {  
    @Override  
    public int compare(Pizza p1, Pizza p2) {  
        return ComparisonChain.start().compare(p1.size, p2.size).compare(p1.nrOfToppings, p2.nrOfToppings).compare(p1.name, p2.name).result();  
        // or in case the fields can be null:  
        /* 
        return ComparisonChain.start() 
           .compare(p1.size, p2.size, Ordering.natural().nullsLast()) 
           .compare(p1.nrOfToppings, p2.nrOfToppings, Ordering.natural().nullsLast()) 
           .compare(p1.name, p2.name, Ordering.natural().nullsLast()) 
           .result(); 
        */  
    }  
});  

这样做要好得多,但是对于最常见的用例,需要一些样板代码:默认情况下,空值的值应较小。对于空字段,您必须提供一个额外的指令给Guava,在这种情况下该怎么做。如果您想做一些特定的事情,但是通常您想要默认情况(即1,a,b,z,null),这是一种灵活的机制。

用Apache Commons CompareToBuilder排序

Collections.sort(pizzas, new Comparator<Pizza>() {  
    @Override  
    public int compare(Pizza p1, Pizza p2) {  
        return new CompareToBuilder().append(p1.size, p2.size).append(p1.nrOfToppings, p2.nrOfToppings).append(p1.name, p2.name).toComparison();  
    }  
});  

像Guava的ComparisonChain一样,该库类可在多个字段上轻松排序,但还定义了null值(即1,a,b,z,null)的默认行为。但是,除非您提供自己的比较器,否则您也不能指定其他任何内容。

从而

最终归结为风味和灵活性的需求(Guava的CompareChain)与简洁的代码(Apache的CompareToBuilder)。

奖金法

我找到了一个不错的解决方案,该解决方案在CodeReview中的优先级顺序中组合了多个比较器MultiComparator

class MultiComparator<T> implements Comparator<T> {
    private final List<Comparator<T>> comparators;

    public MultiComparator(List<Comparator<? super T>> comparators) {
        this.comparators = comparators;
    }

    public MultiComparator(Comparator<? super T>... comparators) {
        this(Arrays.asList(comparators));
    }

    public int compare(T o1, T o2) {
        for (Comparator<T> c : comparators) {
            int result = c.compare(o1, o2);
            if (result != 0) {
                return result;
            }
        }
        return 0;
    }

    public static <T> void sort(List<T> list, Comparator<? super T>... comparators) {
        Collections.sort(list, new MultiComparator<T>(comparators));
    }
}

当然,Apache Commons Collections已经有了一个实用程序:

ComparatorUtils.chainedComparator(comparatorCollection)

Collections.sort(list, ComparatorUtils.chainedComparator(comparators));

22

@Patrick要连续对多个字段进行排序,请尝试ComparatorChain

ComparatorChain是一个比较器,它按顺序包装一个或多个比较器。ComparatorChain依次调用每个Comparator,直到1)任何一个Comparator返回非零结果(然后返回该结果),或2)ComparatorChain耗尽(并返回零)。这种类型的排序与SQL中的多列排序非常相似,并且此类允许Java类在对List进行排序时模拟这种行为。

为了进一步简化类似SQL的排序,可以颠倒列表中任何单个Comparator的顺序。

在调用compare(Object,Object)之后,调用添加新Comparators或更改升序/降序排序的方法将导致UnsupportedOperationException。但是,请注意不要更改基础的比较器列表或定义排序顺序的BitSet。

ComparatorChain的实例不同步。该类在构造时不是线程安全的,但是在所有设置操作完成之后执行多个比较是线程安全的。


20

您始终可以考虑的另一个选择是Apache Commons。它提供了很多选择。

import org.apache.commons.lang3.builder.CompareToBuilder;

例如:

public int compare(Person a, Person b){

   return new CompareToBuilder()
     .append(a.getName(), b.getName())
     .append(a.getAddress(), b.getAddress())
     .toComparison();
}


10
import com.google.common.collect.ComparisonChain;

/**
 * @author radler
 * Class Description ...
 */
public class Attribute implements Comparable<Attribute> {

    private String type;
    private String value;

    public String getType() { return type; }
    public void setType(String type) { this.type = type; }

    public String getValue() { return value; }
    public void setValue(String value) { this.value = value; }

    @Override
    public String toString() {
        return "Attribute [type=" + type + ", value=" + value + "]";
    }

    @Override
    public int compareTo(Attribute that) {
        return ComparisonChain.start()
            .compare(this.type, that.type)
            .compare(this.value, that.value)
            .result();
    }

}

1
我非常喜欢这个策略。谢谢!
Polywhirl先生18年

最有效的方法!谢谢
Zakaria Bouazza

8

对于那些能够使用Java 8流API的人来说,这里有一种更整洁的方法,该方法在此处有详细记录: Lambda和排序

我在寻找与C#LINQ相当的产品:

.ThenBy(...)

我在比较器的Java 8中找到了该机制:

.thenComparing(...)

因此,这是演示算法的代码段。

    Comparator<Person> comparator = Comparator.comparing(person -> person.name);
    comparator = comparator.thenComparing(Comparator.comparing(person -> person.age));

请查看上面的链接,以找到更整洁的方式,并说明与LINQ相比,Java的类型推断如何使它的定义更加笨拙。

这是完整的单元测试,以供参考:

@Test
public void testChainedSorting()
{
    // Create the collection of people:
    ArrayList<Person> people = new ArrayList<>();
    people.add(new Person("Dan", 4));
    people.add(new Person("Andi", 2));
    people.add(new Person("Bob", 42));
    people.add(new Person("Debby", 3));
    people.add(new Person("Bob", 72));
    people.add(new Person("Barry", 20));
    people.add(new Person("Cathy", 40));
    people.add(new Person("Bob", 40));
    people.add(new Person("Barry", 50));

    // Define chained comparators:
    // Great article explaining this and how to make it even neater:
    // http://blog.jooq.org/2014/01/31/java-8-friday-goodies-lambdas-and-sorting/
    Comparator<Person> comparator = Comparator.comparing(person -> person.name);
    comparator = comparator.thenComparing(Comparator.comparing(person -> person.age));

    // Sort the stream:
    Stream<Person> personStream = people.stream().sorted(comparator);

    // Make sure that the output is as expected:
    List<Person> sortedPeople = personStream.collect(Collectors.toList());
    Assert.assertEquals("Andi",  sortedPeople.get(0).name); Assert.assertEquals(2,  sortedPeople.get(0).age);
    Assert.assertEquals("Barry", sortedPeople.get(1).name); Assert.assertEquals(20, sortedPeople.get(1).age);
    Assert.assertEquals("Barry", sortedPeople.get(2).name); Assert.assertEquals(50, sortedPeople.get(2).age);
    Assert.assertEquals("Bob",   sortedPeople.get(3).name); Assert.assertEquals(40, sortedPeople.get(3).age);
    Assert.assertEquals("Bob",   sortedPeople.get(4).name); Assert.assertEquals(42, sortedPeople.get(4).age);
    Assert.assertEquals("Bob",   sortedPeople.get(5).name); Assert.assertEquals(72, sortedPeople.get(5).age);
    Assert.assertEquals("Cathy", sortedPeople.get(6).name); Assert.assertEquals(40, sortedPeople.get(6).age);
    Assert.assertEquals("Dan",   sortedPeople.get(7).name); Assert.assertEquals(4,  sortedPeople.get(7).age);
    Assert.assertEquals("Debby", sortedPeople.get(8).name); Assert.assertEquals(3,  sortedPeople.get(8).age);
    // Andi     : 2
    // Barry    : 20
    // Barry    : 50
    // Bob      : 40
    // Bob      : 42
    // Bob      : 72
    // Cathy    : 40
    // Dan      : 4
    // Debby    : 3
}

/**
 * A person in our system.
 */
public static class Person
{
    /**
     * Creates a new person.
     * @param name The name of the person.
     * @param age The age of the person.
     */
    public Person(String name, int age)
    {
        this.age = age;
        this.name = name;
    }

    /**
     * The name of the person.
     */
    public String name;

    /**
     * The age of the person.
     */
    public int age;

    @Override
    public String toString()
    {
        if (name == null) return super.toString();
        else return String.format("%s : %d", this.name, this.age);
    }
}

7

ComparatorIMO为这种用例手动编写代码是一个糟糕的解决方案。这种临时方法有很多缺点:

  • 没有代码重用。违反DRY。
  • 样板。
  • 错误的可能性增加。

那么解决方案是什么?

首先是一些理论。

让我们用来表示命题“类型A支持比较” Ord A。(从程序的角度来看,您可以将其Ord A视为包含用于比较两个As的逻辑的对象。是的,就像Comparator。)

现在,如果Ord AOrd B,则它们的组合(A, B)也应该支持比较。即Ord (A, B)。如果Ord AOrd BOrd C,然后Ord (A, B, C)

我们可以将此论点扩展到任意Arity,然后说:

Ord A, Ord B, Ord C, ..., Ord ZOrd (A, B, C, .., Z)

我们将此语句称为1。

复合结构的比较将按照您在问题中所描述的那样进行:首先尝试进行第一次比较,然后进行下一个比较,然后进行下一个等等。

那是我们解决方案的第一部分。现在第二部分。

如果你知道Ord A,并知道如何转换BA(调用转换功能f),那么你也可以拥有Ord B。怎么样?好吧,当B要比较两个实例时,首先将它们转换为Ausing f,然后应用Ord A

在这里,我们将转换映射B → AOrd A → Ord B。这就是所谓的逆映射(或comap简称)。

Ord A, (B → A)COMAP Ord B

我们将此语句称为2。


现在,将其应用于您的示例。

您有一个名为的数据类型Person,其中包含type的三个字段String

  • 我们知道Ord String。通过陈述1 ,Ord (String, String, String)

  • 我们可以轻松地从Personto 编写函数(String, String, String)。(只需返回这三个字段。)由于我们知道Ord (String, String, String)并且Person → (String, String, String)通过语句2,我们可以使用comapget Ord Person

QED。


如何实现所有这些概念?

好消息是您不必这样做。已经存在一个实现本文中描述的所有想法的库。(如果您对如何实现这些方法感到好奇,则可以在幕后查看。。)

这是代码的外观:

Ord<Person> personOrd = 
 p3Ord(stringOrd, stringOrd, stringOrd).comap(
   new F<Person, P3<String, String, String>>() {
     public P3<String, String, String> f(Person x) {
       return p(x.getFirstName(), x.getLastname(), x.getAge());
     }
   }
 );

说明:

  • stringOrd是类型的对象Ord<String>。这与我们最初的“支持比较”主张相对应。
  • p3Ord是,需要一个方法Ord<A>Ord<B>Ord<C>,并返回Ord<P3<A, B, C>>。这对应于语句1。(P3代表具有三个元素的乘积。乘积是复合材料的代数术语。)
  • comap对应于comap
  • F<A, B>表示转换函数A → B
  • p 是一种创建产品的工厂方法。
  • 整个表达式对应于语句2。

希望能有所帮助。


5

除了比较方法,您可能只想在Person类中定义几种类型的“ Comparator”子类。这样,您可以将它们传递给标准Collections排序方法。


3

如果您的比较算法是“聪明的”,那我会感到更加困惑。我会使用您建议的众多比较方法。

我唯一的例外是平等。对于单元测试,重写.Equals(在.net中)对我很有用,以确定两个对象之间的几个字段是否相等(而不是引用相等)。


3

如果用户可以通过多种方式订购人员,则还可以在某处将多个Comparator设置为常量。大多数排序操作和排序的集合都将比较器作为参数。


3
//Following is the example in jdk 1.8
package com;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

class User {
    private String firstName;
    private String lastName;
    private Integer age;

    public Integer getAge() {
        return age;
    }

    public User setAge(Integer age) {
        this.age = age;
        return this;
    }

    public String getFirstName() {
        return firstName;
    }

    public User setFirstName(String firstName) {
        this.firstName = firstName;
        return this;
    }

    public String getLastName() {
        return lastName;
    }

    public User setLastName(String lastName) {
        this.lastName = lastName;
        return this;
    }

}

public class MultiFieldsComparision {

    public static void main(String[] args) {
        List<User> users = new ArrayList<User>();

        User u1 = new User().setFirstName("Pawan").setLastName("Singh").setAge(38);
        User u2 = new User().setFirstName("Pawan").setLastName("Payal").setAge(37);
        User u3 = new User().setFirstName("Anuj").setLastName("Kumar").setAge(60);
        User u4 = new User().setFirstName("Anuj").setLastName("Kumar").setAge(43);
        User u5 = new User().setFirstName("Pawan").setLastName("Chamoli").setAge(44);
        User u6 = new User().setFirstName("Pawan").setLastName("Singh").setAge(5);

        users.add(u1);
        users.add(u2);
        users.add(u3);
        users.add(u4);
        users.add(u5);
        users.add(u6);

        System.out.println("****** Before Sorting ******");

        users.forEach(user -> {
            System.out.println(user.getFirstName() + " , " + user.getLastName() + " , " + user.getAge());
        });

        System.out.println("****** Aftre Sorting ******");

        users.sort(
                Comparator.comparing(User::getFirstName).thenComparing(User::getLastName).thenComparing(User::getAge));

        users.forEach(user -> {
            System.out.println(user.getFirstName() + " , " + user.getLastName() + " , " + user.getAge());
        });

    }

}

3

如果我们必须基于多个字段对Person对象进行排序,则相同的代码实现在这里。

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;

public class Person {

private String firstName;
private String lastName;
private int age;

public String getFirstName() {
    return firstName;
}

public void setFirstName(String firstName) {
    this.firstName = firstName;
}

public String getLastName() {
    return lastName;
}

public void setLastName(String lastName) {
    this.lastName = lastName;
}

public int getAge() {
    return age;
}

public void setAge(int age) {
    this.age = age;
}

public Person(String firstName, String lastName, int age) {
    this.firstName = firstName;
    this.lastName = lastName;
    this.age = age;
}


static class PersonSortingComparator implements Comparator<Person> {

    @Override
    public int compare(Person person1, Person person2) {

        // for first name comparison
        int firstNameCompare = person1.getFirstName().compareTo(person2.getFirstName());

        // for last name comparison
        int lastNameCompare = person1.getLastName().compareTo(person2.getLastName());

        // for last name comparison
        int ageCompare = person1.getAge() - person2.getAge();

        // Now comparing
        if (firstNameCompare == 0) {
            if (lastNameCompare == 0) {
                return ageCompare;
            }
            return lastNameCompare;
        }
        return firstNameCompare;
    }
}

public static void main(String[] args) {
    Person person1 = new Person("Ajay", "Kumar", 27);
    Person person2 = new Person("Ajay","Gupta", 23);
    Person person3 = new Person("Ajay","Kumar", 22);


    ArrayList<Person> persons = new ArrayList<>();
    persons.add(person1);
    persons.add(person2);
    persons.add(person3);


    System.out.println("Before Sorting:\n");
    for (Person person : persons) {
        System.out.println(person.firstName + " " + person.lastName + " " + person.age);
    }

    Collections.sort(persons, new PersonSortingComparator());

    System.out.println("After Sorting:\n");
    for (Person person : persons) {
        System.out.println(person.firstName + " " + person.lastName + " " + person.age);
    }
}

}

2
//here threshold,buyRange,targetPercentage are three keys on that i have sorted my arraylist 
final Comparator<BasicDBObject> 

    sortOrder = new Comparator<BasicDBObject>() {
                    public int compare(BasicDBObject e1, BasicDBObject e2) {
                        int threshold = new Double(e1.getDouble("threshold"))
                        .compareTo(new Double(e2.getDouble("threshold")));
                        if (threshold != 0)
                            return threshold;

                        int buyRange = new Double(e1.getDouble("buyRange"))
                        .compareTo(new Double(e2.getDouble("buyRange")));
                        if (buyRange != 0)
                            return buyRange;

                        return (new Double(e1.getDouble("targetPercentage")) < new Double(
                                e2.getDouble("targetPercentage")) ? -1 : (new Double(
                                        e1.getDouble("targetPercentage")) == new Double(
                                                e2.getDouble("targetPercentage")) ? 0 : 1));
                    }
                };
                Collections.sort(objectList, sortOrder);

我之所以提出这个问题,是因为我的代码开始喜欢您的回答了;)
jan groth 2015年

0

如果实现可比接口,则需要选择一个简单的属性进行排序。这称为自然排序。将其视为默认值。当没有提供特定的比较器时,总是使用它。通常这是名称,但是您的用例可能需要其他名称。您可以自由使用可以提供给各种集合API的任意数量的其他比较器,以覆盖自然顺序。

还要注意,通常,如果a.compareTo(b)== 0,则a.equals(b)== true。没关系,但有副作用要注意。在Comparable接口上查看出色的javadocs,您会发现很多关于此的重要信息。


0

以下博客给出了良好的链接比较器示例

http://www.codejava.net/java-core/collections/sorting-a-list-by-multiple-attributes-example

import java.util.Arrays;
import java.util.Comparator;
import java.util.List;

/**
 * This is a chained comparator that is used to sort a list by multiple
 * attributes by chaining a sequence of comparators of individual fields
 * together.
 *
 */
public class EmployeeChainedComparator implements Comparator<Employee> {

    private List<Comparator<Employee>> listComparators;

    @SafeVarargs
    public EmployeeChainedComparator(Comparator<Employee>... comparators) {
        this.listComparators = Arrays.asList(comparators);
    }

    @Override
    public int compare(Employee emp1, Employee emp2) {
        for (Comparator<Employee> comparator : listComparators) {
            int result = comparator.compare(emp1, emp2);
            if (result != 0) {
                return result;
            }
        }
        return 0;
    }
}

呼叫比较器:

Collections.sort(listEmployees, new EmployeeChainedComparator(
                new EmployeeJobTitleComparator(),
                new EmployeeAgeComparator(),
                new EmployeeSalaryComparator())
        );

0

史蒂夫的答案开始,可以使用三元运算符:

public int compareTo(Person other) {
    int f = firstName.compareTo(other.firstName);
    int l = lastName.compareTo(other.lastName);
    return f != 0 ? f : l != 0 ? l : Integer.compare(age, other.age);
}

0

用Java中的hashcode方法比较两个对象很容易

public class Sample{

  String a=null;
  String b=null;

  public Sample(){
      a="s";
      b="a";
  }
  public Sample(String a,String b){
      this.a=a;
      this.b=b;
  }
  public static void main(String args[]){
      Sample f=new Sample("b","12");
      Sample s=new Sample("b","12");
      //will return true
      System.out.println((s.a.hashCode()+s.b.hashCode())==(f.a.hashCode()+f.b.hashCode()));

      //will return false
      Sample f=new Sample("b","12");
      Sample s=new Sample("b","13");
      System.out.println((s.a.hashCode()+s.b.hashCode())==(f.a.hashCode()+f.b.hashCode()));

}

请不要那样做。哈希码不应用于相等性比较,而应用于哈希表索引。哈希冲突可能导致两个不同的对象相等。如果发生哈希冲突,即使哈希表也依赖于真实相等
诺埃尔·威德默

0

通常,compareTo()每当我必须进行多级排序时,我都会像这样覆盖我的方法。

public int compareTo(Song o) {
    // TODO Auto-generated method stub
    int comp1 = 10000000*(movie.compareTo(o.movie))+1000*(artist.compareTo(o.artist))+songLength;
    int comp2 = 10000000*(o.movie.compareTo(movie))+1000*(o.artist.compareTo(artist))+o.songLength;
    return comp1-comp2;
} 

在此,优先选择电影名称,然后再选择艺术家,最后是songLength。您只需要确保这些乘数相距足够远,就不会越过彼此的边界。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.