【问题标题】:Strange sorting with reversed using new API on Java8使用 Java8 上的新 API 进行反向排序的奇怪排序
【发布时间】:2017-08-19 12:03:25
【问题描述】:

Java8 支持一种对集合进行排序的新方法。乍一看,这看起来很优雅,但我陷入了一个我发现它相当混乱的情况。

情况是应用链式排序属性,没关系。但是当使用 reverse() 时,整个比较器是反转的。这会导致混乱的调用顺序

对于选择升序名称和降序年龄,API 调用看起来像

 Comparator
   .comparing(Person::getName).reversed()
   .thenComparingInt(Person::getAge).reversed()

用文字来说:按姓名降序比较,然后按年龄升序比较,然后将整个比较器反转。

对我来说,情况 b) 和 c) 看起来很奇怪且不直观。

有没有更好、更易读、更直观的方式来表达升序/降序的多重排序?

我使用了以下代码

POJO

class Person {
    String name;
    int age;

    public Person() {    }

    public int getAge() {
        return age;
    }

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

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

    @Override
    public String toString() {
        return name + '(' + age + ')';
    }
}

测试代码

public class Sort { 
    public static void main(String[] args) {

        List<Person> persons = Arrays.asList(
            new Person("michael", 28),
            new Person("peter", 29),
            new Person("marion", 21),
            new Person("peter", 22),
            new Person("hanna", 24),
            new Person("hanna", 27),
            new Person("albert", 23));

        // a) ascending name and age
        Collections.sort(persons, Comparator
            .comparing(Person::getName)
            .thenComparingInt(Person::getAge));
        System.out.println(persons);

        // b) ascending name and descending age
        Collections.sort(persons, Comparator
            .comparing(Person::getName).reversed()
            .thenComparingInt(Person::getAge).reversed());
        System.out.println(persons);

        // c) descending name and age
        Collections.sort(persons,  Comparator
            .comparing(Person::getName)
            .thenComparingInt(Person::getAge).reversed());
        System.out.println(persons);

        // d) descending name and ascending age
        Collections.sort(persons, Comparator
            .comparing(Person::getName).reversed()
            .thenComparingInt(Person::getAge));
        System.out.println(persons);
    }
}

结果列表

[albert(23), hanna(24), hanna(27), marion(21), michael(28), peter(22), peter(29)]
[albert(23), hanna(27), hanna(24), marion(21), michael(28), peter(29), peter(22)]
[peter(29), peter(22), michael(28), marion(21), hanna(27), hanna(24), albert(23)]
[peter(22), peter(29), michael(28), marion(21), hanna(24), hanna(27), albert(23)]

【问题讨论】:

    标签: java collections


    【解决方案1】:

    与任何复杂的表达式一样,最简单的方法是将其拆分为多个以提高可读性。在这种情况下,您可以简单地这样做:

    Comparator<Person> ascNameComparator = Comparator.comparing(Person::getName);
    Comparator<Person> descAgeComparator = Comparator.comparingInt(Person::getAge).reversed();
    
    Comparator<Person> personComparator = ascNameComparator.thenComparing(descAgeComparator);
    

    【讨论】:

      【解决方案2】:

      这个怎么样(使用静态导入使其更简洁):

      Comparator<Person> ascNameDescAgeComp = 
         comparing(Person::getName)
         .thenComparing(comparingInt(Person::getAge).reversed());
      Collections.sort(persons, ascNameDescAgeComp );
      

      【讨论】:

      • 更简洁:persons.sort(ascNameDescAgeComp);
      【解决方案3】:

      为什么不使用流?

      你可以试试这样的:

      persons =  persons.stream().sorted( (p,op) -> p.getName().compareTo(op.getName()) + Integer.compare(op.getAge(),p.getAge())).collect(Collectors.toList());
      

      【讨论】:

      • 对不起,此代码不会改变人的顺序
      • 当然不是,但是你可以为persons分配一个新的引用
      猜你喜欢
      • 2021-06-26
      • 2018-11-11
      • 2011-03-13
      • 1970-01-01
      • 2014-09-23
      • 2012-12-17
      • 2011-03-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多