美文网首页我爱编程
Java边用边学: 我有5种方法写排序

Java边用边学: 我有5种方法写排序

作者: 朱和 | 来源:发表于2018-09-01 23:18 被阅读0次

需求及代码分析

下面的一段简单的排序代码(按照员工的年龄的倒序排列),可以有大概这么5种写法:

final List<Employee> employees = ...;

// 1.匿名类
employees.sort(new Comparator<Employee>() {
  @Override
  public int compare(Employee e1, Employee e2) {
    return Integer.compare(e1.getAge(), e2.getAge());
  }
}.reversed());

// 2.Lambda
// e2在前,倒序
employees.sort(
  (e1, e2) -> Integer.compare(e2.getAge(), e1.getAge())
);

// 3.Named Lambda
final Comparator<Employee> comparator = 
    (e1, e2) -> Integer.compare(e1.getAge(), e2.getAge());
employees.sort(comparator.reversed());

// 4.复用 + Lambda
employees.sort(
  comparingInt((Employee e) -> e.getAge()).reversed()
);

// 5.复用 + 方法引用
employees.sort(
  comparingInt(Employee::getAge).reversed()
);
  1. 匿名类

没什么好说的,Java 8之前的经典写法了。(至于是不是需要调用reversed()还是直接把e2放在e1前面,这个后面有答案)

  1. Lambda

Java 8+的Lambda,由于需要实现倒序,所以程序猿很注意的把e2写在了e1前面了(并配有完美的注释)

  1. 命名的Lambda

由于Lambda是没有名字的,所以想给它来个倒序,不得不给它先取个名字,然后就可以直接调用reversed()来声明我这个是倒序啊!

  1. 复用 + Lambda

Java自带的类库其实已经很丰富了,所以直接拿来用吧:Comparator.comparingInt(ToIntFunction)完美符合当前需求,用一段Lambda实现了ToIntFunction。

  1. 复用 + 方法引用

同上,用方法引用替换了Lambda。

讨论/争论开始

很容易写错的排序

这个排序看上去简单,但其实写错也很容易,大概的错误点包括:

  • 都写成e1或e2:
Integer.compare(e1.getAge(), e1.getAge());
  • 比较的属性不一致:
Integer.compare(e1.getAge(), e2.getLevel());
  • e1和e2的前后位置(涉及到倒序还是顺序)
    • 我们的实现3.Named Lambda的排序其实写反了。它的Lambda是倒序(没错啊,我们的业务是需要倒序),问题是它在使用的时候再次反序了下,那就又回到顺序了。
都写成e1/e2 比较的属性不一致 e1和e2的前后位置
#1.匿名类 中招 中招 中招
#2.Lambda 中招 中招 中招
#3.命名的Lambda 中招 中招 中招
#4.复用+Lambda
#5.复用+方法引用

实现#4和#5就很聪明,直接用Java的类库,正确性完全有保证(e1和e2的谁前谁后无需关心)。对于倒序则简单的调用下reversed(),完事!另外#5的方法引用让可读性更进一步。

亲民的函数式编程

从左到右读完这句

employees.sort(
    comparingInt(Employee::getAge).reversed()
);

大概可以获得下列信息:

  • 对列表进行排序需要:
    • 按照员工的年龄排序
    • 且是倒序

就这么读过,代码的自说明能力完整的表述了其功能。

然后我们对比下#2.Lambda:

employees.sort(
  (e1, e2) -> Integer.compare(e2.getAge(), e1.getAge())
);

其解读大概是这样的:

  • 对列表进行排序需要:
    • 嗯,e1和e2应该是前后相邻的两个Employee实例
    • 都取出了年龄来比较
    • e2在前,应该是倒序吧(Code Review的同学比较严谨,查了下Javadoc)。嗯,倒序!

如果需求再复杂点,那我们第5种的优势会更明显。

譬如先按年龄的倒序排列,如果年龄相同,则按性别的顺序排列:

employees.sort(
    comparingInt(Employee::getAge).reversed()   // 年龄(倒序)
    .thenComparing(Employee::getGender)        // 第二序列是性别(顺序)
);

换成其他几种写法,估计很难一眼看懂了。

结论

  • 方法引用优先于Lambda
  • 有用的Java类库,譬如Comparator, Collectors

希望这篇博文能对你有所帮助,喜欢的话点个赞吧!


相关文章

  • Java边用边学: 我有5种方法写排序

    需求及代码分析 下面的一段简单的排序代码(按照员工的年龄的倒序排列),可以有大概这么5种写法: 匿名类 没什么好说...

  • 边学边用,边用边学

    我一直想学很多东西,却一直没学好,甚至还没开始真正学习。 大学的时候,我就想学很多东西。想学习谈判,学习演讲,写一...

  • 边学边用

    7月14日《人生效率手册》5 书里说到,如果我们不能将所学的理论与实践相结合,换句话说,在实践场景中,无法调用知识...

  • 边学边用

    2020.08.16 星期天 阴雨天 早上去辅导的时候,马老师给学生买了高中语法书,给我...

  • 边学边用

    分享424 有这么一句话:有人不让你成功,但是没有办法不让你成长。成长是自己的事情,成长应该成为每一个人的状态。 ...

  • 边学边用

    我阅读的书目是《致青年老师》 读书笔记分享:在读《致青年老师》第三辑《心里装着学生》,想学生之所想,急学生之所急,...

  • markdown边学边用

    ```代码块``` ~~删除线~~ 有序列表 数字+英文句号 后面还有空格 反斜杠转义特殊字符\``` *** 分...

  • 边学边用 - 草稿

    刘斌焦点网络四期驻马店坚持分享第260天 看到刘老师分享的边学边用,用中才会有更好的进步,很有感触。这一次遇到实际...

  • excel边用边学

    vlookup函数:ƒ(x)=vlookup(lookup_value,table_array,col_index...

  • Docker 边学边用

    富 Web 时代,应用变得越来越强大,与此同时也越来越复杂。集群部署、隔离环境、灰度发布以及动态扩容缺一不可,而容...

网友评论

    本文标题:Java边用边学: 我有5种方法写排序

    本文链接:https://www.haomeiwen.com/subject/yekpwftx.html