我想对按一个属性升序,然后按另一个属性降序的对象列表进行排序.

例如,假设以下列表为(age, name):

(25, Alice), (25, Bob), (30, Charlie), (25, David), (30, Eve)

我试着按年龄升序,然后按名字降序,如下所示:

(25, David), (25, Bob), (25, Alice), (30, Eve), (30, Charlie)

我试着使用Stream.sortedComparator来实现这一点,但我不确定如何在不反转前面的比较器的情况下反转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,但得到的比较结果为

age by descending, then name by descending:

(30, Eve), (30, Charlie), (25, David), (25, Bob), (25, Alice)

但正如我上面所说的,我试图实现的比较是

age by ascending, then name by descending:

(25, David), (25, Bob), (25, Alice), (30, Eve), (30, Charlie)

推荐答案

您当前的代码正在创建一个比较器,该比较器以自然顺序比较年龄和姓名,然后反转that个比较器.您只需要颠倒名称的比较,实现起来相对简单.

  1. 使用Comparator#thenComparing(Function,Comparator)超载.第二个参数是一个比较器,告诉它how比较函数提取的对象.

  2. 使用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]

Java相关问答推荐

在Spring Boot中测试时出现SQL语法错误

为什么接口中的主函数而不是类中的主函数在Java 17中编译和运行没有问题?

具有额外列的Hibert多对多关系在添加关系时返回NonUniqueHealthExcellent

Java:根据4象限中添加的行数均匀分布行的公式

无法找到符号错误—Java—封装

JavaFX Maven Assembly插件一直打包到错误的JDK版本

SpringBootreact 式Web应用程序的Spring Cloud Configer服务器中的资源控制器损坏

使用Testcontainers与OpenLiberty Server进行集成测试会抛出SocketException

通过Spring Security公开Spring Boot执行器端点

带错误BER验证的itext8签名返回pdf

Java ArrayList的整数和数组的泛型

WebSockets和Spring Boot安全性出现错误401

为什么有两种实现来检索数组类的组件类型?

buildDir:File!&#的getter解决方案是什么?39.被抛弃

我可以在@Cacheable中使用枚举吗

JavaFX:无论何时显示应用程序,如何更改组件/ node 位置?

如何在IntelliJ IDEA的Build.sbt中添加外部JAR文件?

在Java中使用StorageReference将数据从Firebase存储添加到数组列表

如何通过gradle命令行从build.gradle获得Java targetCompatibility

Java编译器是否进行了持续的折叠优化,以及如何进行判断?