假设你有一些对象,它们有几个字段可以比较:
public class Person {
private String firstName;
private String lastName;
private String age;
/* Constructors */
/* Methods */
}
所以在这个例子中,当你问if:
a.compareTo(b) > 0
你可能会问a的姓是不是在b的姓之前,或者a的年龄是不是比b大,等等……
在不增加不必要的混乱或开销的情况下,在这些类型的对象之间进行多重比较的最干净的方法是什么?
comparable接口只允许通过一个字段进行比较
在我看来,添加大量的比较方法(如compareByFirstName(), compareByAge()等)是混乱的。
那么最好的解决办法是什么呢?
如果我们必须基于多个字段对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);
}
}
}
晚做总比不到好——如果你正在寻找不必要的混乱或开销,那么很难同时在最少的代码/快速执行方面击败下面的方法。
数据类:
public class MyData {
int id;
boolean relevant;
String name;
float value;
}
比较器:
public class MultiFieldComparator implements Comparator<MyData> {
@Override
public int compare(MyData dataA, MyData dataB) {
int result;
if((result = Integer.compare(dataA.id, dataB.id)) == 0 &&
(result = Boolean.compare(dataA.relevant, dataB.relevant)) == 0 &&
(result = dataA.name.compareTo(dataB.name)) == 0)
result = Float.compare(dataA.value, dataB.value);
return result;
}
}
如果你只是想按自定义顺序对集合进行排序,那么下面的代码就更清晰了:
myDataList.sort((dataA, dataB) -> {
int result;
if((result = Integer.compare(dataA.id, dataB.id)) == 0 &&
(result = Boolean.compare(dataA.relevant, dataB.relevant)) == 0 &&
(result = dataA.name.compareTo(dataB.name)) == 0)
result = Float.compare(dataA.value, dataB.value);
return result;
});
另一个可以考虑的选项是Apache Commons。它提供了很多选项。
import org.apache.commons.lang3.builder.CompareToBuilder;
Ex:
public int compare(Person a, Person b){
return new CompareToBuilder()
.append(a.getName(), b.getName())
.append(a.getAddress(), b.getAddress())
.toComparison();
}