Java8 特性详解 --Lambda 表达式之排序

本贴最后更新于 2769 天前,其中的信息可能已经水流花落

前言

java9 都要发布了,java8 的一些特性你们掌握了吗?
今天给大家带来的是 java8 核心特性之一的 Lambda 表达式在数组/集合排序中的应用.

正文

首先,为本文创建一个测试类:

public class Student implements Comparable<Student> { private int age; private String nameEn; private int grade; public Student(int age, String nameEn, int grade) { this.age = age; this.nameEn = nameEn; this.grade = grade; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getNameEn() { return nameEn; } public void setNameEn(String nameEn) { this.nameEn = nameEn; } public int getGrade() { return grade; } public void setGrade(int grade) { this.grade = grade; } public static int compare(Student s1, Student s2) { return Integer.compare(s1.getAge(), s2.getAge()); } @Override public int compareTo(Student s) { return Integer.compare(this.getAge(), s.getAge()); } } ... /** * 初始化数据 * * @return */ public static List<Student> initData() { List<Student> list = new ArrayList<>(); list.add(new Student(11, "zhangsan", 5)); list.add(new Student(12, "lisi", 5)); list.add(new Student(9, "wangwu", 6)); list.add(new Student(13, "zhaoliu", 6)); list.add(new Student(8, "tianqi", 3)); list.add(new Student(6, "wangba", 1)); list.add(new Student(8, "jiujiu", 2)); return list; } ...

传统排序方式

1.在 Java 8 之前,对集合进行排序要为 Comparator 创建一个匿名内部类用来排序,比如,按照 age 字段从小到大排序:

/** * 传统匿名内部类比较器 */ @Test public void soreted1() { List<Student> list = Java8SortedDemo.initData(); list.sort(new Comparator<Student>() { @Override public int compare(Student s1, Student s2) { return Integer.compare(s1.getAge(), s2.getAge()); } }); Assert.assertEquals(list.get(0).getNameEn(), "wangba"); }

2.或者让 Student 实现 Comparable 接口,复写 compareTo 方法,同样按照 age 字段从小到大排序:

... @Override public int compareTo(Student s) { return Integer.compare(this.getAge(), s.getAge()); } ... /** * 实现Comparable接口 */ @Test public void soreted2() { List<Student> list = Java8SortedDemo.initData(); Collections.sort(list); Assert.assertEquals(list.get(0).getNameEn(), "wangba"); }

java8 排序方式

3.在 java8 中引入了重要的特性之一 lambda,根据 Lambda 表达式的介绍,我们现在可以不使用匿名内部类,只使用简单实用的语义就可以得到相同的结果,按照 age 字段从小到大排序:

/** * java8的Lambda,显式指定比较类型 */ @Test public void soreted3() { List<Student> list = Java8SortedDemo.initData(); list.sort((Student s1, Student s2) -> Integer.compare(s1.getAge(), s2.getAge())); Assert.assertEquals(list.get(0).getNameEn(), "wangba"); }

4.我们甚至可以省略类型,让编译器自行推测,按照 age 字段从小到大排序:

/** * java8的Lambda,不指定比较类型 */ @Test public void soreted4() { List<Student> list = Java8SortedDemo.initData(); list.sort((s1, s2) -> Integer.compare(s1.getAge(), s2.getAge())); Assert.assertEquals(list.get(0).getNameEn(), "wangba"); }

5.我们还可以使用静态方法排序,按照 age 字段从小到大排序:

... public static int compare(Student s1, Student s2) { return Integer.compare(s1.getAge(), s2.getAge()); } ... /** * 自定义静态方法 */ @Test public void soreted5() { List<Student> list = Java8SortedDemo.initData(); list.sort(Student::compare); Assert.assertEquals(list.get(0).getNameEn(), "wangba"); }

6.当然,java8 为我们准备好了通用的 Comparator.comparing 方法,按照 age 字段从小到大排序:

/** * Comparator提供的静态方法 */ @Test public void soreted6() { List<Student> list = Java8SortedDemo.initData(); list.sort(Comparator.comparing(Student::getAge)); Assert.assertEquals(list.get(0).getNameEn(), "wangba"); }

java8 排序方法拓展:

java8 同样让我们具备编写更复杂逻辑排序的方法表达式,

7.比如,反转排序,按照 age 字段从大到小排序:

/** * 反转排序 */ @Test public void soreted7() { List<Student> list = Java8SortedDemo.initData(); list.sort(Comparator.comparing(Student::getAge).reversed()); Assert.assertEquals(list.get(0).getNameEn(), "zhaoliu"); }

8.比如,多字段组合排序,先按照 grade 从大到小,相同则按照 age 从大到小排序:

/** * 多字段组合排序(匿名类方式) */ @Test public void soreted8() { List<Student> list = Java8SortedDemo.initData(); list.sort((s1, s2) -> { if (Integer.compare(s1.getGrade(), s2.getGrade()) != 0) { return Integer.compare(s2.getGrade(), s1.getGrade()); } return Integer.compare(s2.getAge(), s1.getAge()); }); Assert.assertEquals(list.get(0).getNameEn(), "zhaoliu"); }

9.java8 的 Comparator 为我们准备了更便利的链式风格组合排序方式,先按照 grade 从大到小,相同则按照 age 从小到大排序:

/** * 多字段组合排序(链式接口) */ @Test public void soreted9() { List<Student> list = Java8SortedDemo.initData(); list.sort(Comparator.comparing(Student::getGrade).reversed().thenComparing(Student::getAge)); Assert.assertEquals(list.get(0).getNameEn(), "wangwu"); }

总结

Lambda 表达式虽然不是什么新鲜玩意了,但是灵活使用 java8 提供的语法糖,能让你书写出更简洁,语义化的代码...
本文所示 demo 已经上传 github,各位随时可以下载查阅:Java8 特性详解--Lambda 表达式之排序

  • B3log

    B3log 是一个开源组织,名字来源于“Bulletin Board Blog”缩写,目标是将独立博客与论坛结合,形成一种新的网络社区体验,详细请看 B3log 构思。目前 B3log 已经开源了多款产品:SymSoloVditor思源笔记

    1063 引用 • 3455 回帖 • 165 关注
  • 代码
    467 引用 • 586 回帖 • 9 关注
  • Java

    Java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的。Java 技术具有卓越的通用性、高效性、平台移植性和安全性。

    3194 引用 • 8214 回帖
  • Lambda
    24 引用 • 19 回帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...
  • wizardforcel

    eta 表示法真是太好用了 ╮(╯_╰)╭

  • someone

    看使用场景吧,不仅仅是自己用的爽,也要让同事看得爽,我司目前使用jdk8,因此大家或多或少倾向于使用这些东西,当然 如果还在jdk6时代的童鞋,这些语法糖也没法用.