我想对对象列表按某个属性升序排序,然后按另一个属性降序排序。
例如,将以下列表视为
(age, name)
:
(25, Alice), (25, Bob), (30, Charlie), (25, David), (30, Eve)
我试图按年龄升序排序,然后按名称降序排序,如下所示:
(25, David), (25, Bob), (25, Alice), (30, Eve), (30, Charlie)
我尝试使用
Stream.sorted
和 Comparator
来实现此目的,但我不确定如何在不反转之前的比较器的情况下反转 Comparator.thenComparing
。
看看这个例子:
import java.util.Comparator;
import java.util.List;
public class Dummy {
private static class Person {
private final int age;
private final String name;
public Person(int age, String name) {
this.age = age;
this.name = name;
}
public int getAge() { return age; }
public String getName() { return name; }
@Override
public String toString() { return "(" + age + ", " + name + ")"; }
}
public static void main(String[] args) {
var people = List.of(
new Person(25, "Alice"),
new Person(25, "Bob"),
new Person(30, "Charlie"),
new Person(25, "David"),
new Person(30, "Eve")
);
System.out.println(people);
var sortedPeople = people
.stream()
.sorted(
Comparator
.comparing(Person::getAge)
.thenComparing(Person::getName)
.reversed()
)
.toList();
System.out.println(sortedPeople);
}
}
如您所见,我将
reversed
应用于比较器,但结果比较变为
年龄按降序排列,然后姓名按降序排列:
(30, Eve), (30, Charlie), (25, David), (25, Bob), (25, Alice)
但正如我上面所说,我想要实现的比较是
年龄按升序排列,然后姓名按降序排列:
(25, David), (25, Bob), (25, Alice), (30, Eve), (30, Charlie)
您当前的代码正在创建一个比较器,以自然升序比较年龄和姓名,然后反转 that 比较器。只需要反转名称的比较即可,实现起来比较简单。
Comparator#thenComparing(Function,Comparator)
过载。第二个参数是一个比较器,告诉它如何比较函数提取的对象。
Comparator.reverseOrder()
获得一个反转自然顺序的比较器。
例如:
import static java.util.Comparator.comparing;
import static java.util.Comparator.reverseOrder;
import java.util.ArrayList;
public class Main {
public static void main(String[] args) throws Exception {
var people = new ArrayList<Person>(5);
people.add(new Person(25, "Alice"));
people.add(new Person(25, "Bob"));
people.add(new Person(30, "Charlie"));
people.add(new Person(25, "David"));
people.add(new Person(30, "Eve"));
printPeople("UNSORTED", people);
people.sort(comparing(Person::age).thenComparing(Person::name, reverseOrder()));
printPeople("SORTED", people);
}
static void printPeople(String label, Iterable<Person> people) {
System.out.println(label);
System.out.println("-".repeat(label.length()));
people.forEach(System.out::println);
System.out.println();
}
record Person(int age, String name) {}
}
输出:
UNSORTED
--------
Person[age=25, name=Alice]
Person[age=25, name=Bob]
Person[age=30, name=Charlie]
Person[age=25, name=David]
Person[age=30, name=Eve]
SORTED
------
Person[age=25, name=David]
Person[age=25, name=Bob]
Person[age=25, name=Alice]
Person[age=30, name=Eve]
Person[age=30, name=Charlie]