【问题标题】:Java 8 - Compare multiple fields in different order using ComparatorJava 8 - 使用比较器以不同的顺序比较多个字段
【发布时间】:2019-01-05 00:27:40
【问题描述】:

我喜欢使用 Java 8 Comparator 根据三个属性对对象的 List 进行排序。要求按此顺序排序 - 姓名升序、年龄降序、城市升序。如果我在 `Age 上使用reversed(),它也会反转以前排序的条目。这是我尝试过的:

Comparator.comparing((Person p) -> p.getName())
          .thenComparingInt(p -> p.getAge())
          .reversed()
          .thenComparing(p -> p.getCity());

【问题讨论】:

  • e.getAge() 是错字吗?而不是应该是p.getAge() ?
  • 应该是 p.getAge()。该问题已使用错字修复进行编辑。

标签: java list java-8 comparator


【解决方案1】:

使用Comparator.reverseOrder():

.thenComparing(Person::getAge, Comparator.reverseOrder())

如果你想避免自动装箱,你可以这样做

.thenComparing((p1, p2) -> Integer.compare(p2.getAge(), p1.getAge()))

或者

.thenComparing(Comparator.comparingInt(Person::getAge).reversed())

【讨论】:

  • 只是好奇有什么区别?
  • @YCF_L reversed() 反转整个前面的链。
  • 我更喜欢最后一个选项。可能是口味问题。
  • 就像Ole V.V.,我发现第三个选项是最好的(就可读性+性能而言)。
  • 在基于多个字段进行比较时如何处理姓名和年龄的 NULL 值
【解决方案2】:

没有必要使用Comparator::reverse的方法。既然要根据整数进行逆向比较,只需将年龄-p.getAge()取反,就会降序排列:

Comparator.comparing((Person p) -> p.getName())
          .thenComparingInt(p -> -p.getAge())
          .thenComparing(p -> p.getCity());

【讨论】:

  • 不错的一个...除非您恰好是-2147483648岁。 :P
  • @shmosel Integer.signum 可能会有所帮助。
  • 理论上不错,但实际上在阅读此类代码时更容易错过减号。因此我建议使用shmosel's third solution
  • 接受@shmodel 的答案是正确的,因为它通常会回答如何进行此类排序/比较。
  • @Nikolas 关于Integer.MIN_VALUE 的评论不是我的;) 至于建议的减号+注释解决方案:我曾经写过这样的代码,但现在我避免了。现在,我绝对喜欢不言自明的代码而不是注释代码,因为代码不能(至少不容易)撒谎,而 cmets 可以。此外,这样的评论引入了两个“事实来源”,修改此类代码的每个人都必须更新两者。太多次我看到有人修改了代码但忘记更新/删除这样的评论。这是a nice read about commenting
猜你喜欢
  • 2021-05-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-28
  • 2015-11-02
  • 2020-12-16
  • 2015-10-11
相关资源
最近更新 更多