對數據進行排序是日常常常會用到的操做之一,使用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的尾遞歸