对数据进行排序是日常常常会用到的操做之一,使用Jav8排序能够减小你在排序这方面的代码量,优化你的代码。html
定义个实体类User,拥有姓名name,年龄age,积分credits三个属性,定义一个包含User的集合,用于排序,下面是代码java
/* 这里偷个懒,用lombok注解生成实体类getset等一些基本方法 */ @Data @AllArgsConstructor @NoArgsConstructor public class User { private String name; private Integer age; private Integer credits; }
初始化待排序的集合app
private List<User> users = Lists.newArrayList( new User("jack",17,10), new User("jack",18,10), new User("jack",19,11), new User("apple",25,15), new User("tommy",23,8), new User("jessica",15,13) );
根据User年龄从小到大排序,使用Collections.sort方法,经过Comparator的匿名内部类实现ide
@Test public void traditionCompareByName(){ Collections.sort(users, new Comparator<User>() { @Override public int compare(User o1, User o2) { return o1.getAge() - o2.getAge(); } }); for (User user : users) { System.out.println(user); } }
结果函数
User(name=jessica, age=15, credits=13) User(name=jack, age=17, credits=10) User(name=jack, age=18, credits=10) User(name=jack, age=19, credits=11) User(name=tommy, age=23, credits=8) User(name=apple, age=25, credits=15) Process finished with exit code 0
这里使用lambda表达式来代替匿名内部类,而且使用list接口下的sort方法(java8新增长),再链式输出测试
@Test public void traditionCompareByNameInJava8(){ users.sort((o1, o2) -> o1.getAge() - o2.getAge()); users.forEach(user -> System.out.println(user)); }
输出结果就再也不显示了
固然还能够经过方法引用进一步的简化,这里使用Comparator下的comparingInt进行排序,使用User::getAge得到年龄,默认从小到大正向排序优化
import static java.util.Comparator.comparingInt; @Test public void traditionCompareByNameInJava8(){ users.sort(comparingInt(User::getAge)); users.forEach(System.out::println); }
简单对比一下,能够发现使用Java8的排序对于简单的排序不管是从代码量仍是能够阅都是比以前的匿名内部类实现compare方法要好的。code
一样是经过匿名内部类这是此次将 o1 - o2 的顺序调换一下htm
@Test public void traditionCompareByNameReverse(){ Collections.sort(users, new Comparator<User>() { @Override public int compare(User o1, User o2) { return o2.getAge() - o1.getAge(); } }); }
和匿名内部类的颠倒同样,只是这里有之间的类库反转blog
@Test public void traditionCompareByNameInJava8Reverse(){ users.sort((o1, o2) -> o1.getAge() - o2.getAge()); }
在比较器后面增长reversed便可,链式调用是java8的风格之一
@Test public void traditionCompareByNameInJava8Reverse(){ users.sort(comparingInt(User::getAge).reversed()); }
一样是阅读性,原先的匿名内部类方法不只阅读困难,一个简单的倒序也须要先去观察o2-o1仍是o1-o2才能得出,而Java8的方法不只代码简洁,可读性还很高,compare getAge读出是经过年龄进行排序,reversed读出是倒序。
按照姓名,年龄与积分的顺序依次排序,也就是多条件组合排序
让咱们看看传统的方式该如何实现
@Test public void traditionCombinationCompare(){ Collections.sort(users, new Comparator<User>() { @Override public int compare(User o1, User o2) { if (o1.getName().equals(o2.getName())) { if (o1.getAge().equals(o2.getAge())) { return o1.getAge() - o2.getAge(); } else { return o1.getCredits() - o2.getCredits(); } } else { return o1.getName().compareTo(o2.getName()); } } }); }
这样的代码我相信谁都不太想看,我本身写完都须要验证一遍以保证真的没有哪里逻辑写错,这样的作法不只效率底下,还容易犯错,这种代码更是他人的噩梦。
thenComparing
实现链式调用@Test public void traditionCombinationCompareInJava8(){ users.sort(comparing(User::getName) .thenComparing(User::getAge) .thenComparing(User::getCredits)); }
可读性也很好,这样的代码几乎连注释都省去了,很清晰的能够看出排序的顺序,修改起来也很容易,而上面的代码若是要修改为另一种次序,整个嵌套逻辑结构条件都要改动。
@Test public void traditionCombinationCompareInJava8(){ users.sort(comparing(User::getName) .thenComparing(User::getAge, (o1, o2) -> o2 - o1) .thenComparing(User::getCredits)); }
o2 - o1
这样的代码仍是有一些命令式的风格,即包含了具体的实现过程(o2 -o1
这样的代码),thenComparaing方法能够直接接受一个排序器,所以咱们只要直接将倒序的排序器当作参数传入便可,代码以下@Test public void traditionCombinationCompareInJava8(){ users.sort(comparing(User::getName) .thenComparing(comparing(User::getAge).reversed()) .thenComparing(User::getCredits)); users.forEach(System.out::println); }
很清晰的能够看到第二行的getAge是倒序,而其余的属性依旧是正序,建议你们使用链式写法的时候像上面同样分行,提升可读性
但愿这篇文章能对你有所帮助 :)
上一篇:开始Java8之旅(四) --四大函数接口
下一篇:开始Java8之旅(六) --使用lambda实现Java的尾递归