如何用Java8 Stream API找到心儀的女朋友
傳統的的Java 集合操作是有些囉嗦的,當我們需要對結合元素進行過濾,排序等操作的時候,通常需要寫好幾行程式碼以及定義臨時變數。
而Java8 Stream API 可以極大簡化這一操作,程式碼行數少,且易讀。
我們以“找女朋友”為例來看看Java8的Stream API相比傳統寫法有多香。假設我們定義了一個女朋友類,具有幾個關鍵的指標:姓名,身高,體重,顏值。如下所示:
class Girl { private String name; private int height; private int weight; private int score; // 省略get,set及hashCode等方法 }
我們有一批適齡女青年名單,如下:
public static List<Girl> initGirlList(){ List<Girl> result = new ArrayList<>(); result.add(new Girl("趙小花",170,60,6)); result.add(new Girl("錢小花",171,62,7)); result.add(new Girl("孫小花",172,59,8)); // 省略.... return result; }
心儀女朋友的篩選條件
假設心儀的女朋友是:體重,身高適中,顏值越高越好。本次設定的條件是找出:身高>=162 並且 體重<=53的女孩,然後按顏值排序前三名。
Java7的寫法
資料去重
由於資料可能有重複,這會干擾我們的篩選,因此,第一步先去掉重複資料。程式碼如下:
List<Girl> girlList = initGirlList();// 初始化一批資料 // 資料去重 List<Girl> distinctGirl = new ArrayList<>(); for (Girl g: girlList){ if(!distinctGirl.contains(g)){ distinctGirl.add(g); } }
這裡new了一個新的distinctGirl
來存放去重之後的資料,程式碼很簡單,沒啥可說的。
篩選資料
下面我們要去掉不合格的資料,本次篩選條件是身高>=162 並且 體重<=53,程式碼如下:
// 過濾身高,體重不符合的
List<Girl> girlTemp = new ArrayList<>();
for(Girl g: distinctGirl){
if(g.getHeight() >= 162 && g.getWeight() <= 53){
girlTemp.add(g);
}
}
這裡運用上一步中去重之後的distinctGirl
,遍歷,並將符合條件的放入新的list girlTemp
,這裡又建立了一箇中間list。
資料排序
經過上面囉嗦的兩步,我們得到了符合我們要求的資料,現在我們需要根據顏值高低進行排名,程式碼如下:
Collections.sort(girlTemp, new Comparator<Girl>() {
@Override
public int compare(Girl g1, Girl g2) {
BigDecimal score1 = new BigDecimal(g1.getScore());
BigDecimal score2 = new BigDecimal(g2.getScore());
return score2.subtract(score1).intValue();
}
});
這裡使用了Collections
工具類的sort
方法,傳遞了一個匿名類,並在其compare
方法中實現了排序的邏輯,這依然是傳統集合排序的操作。
輸出結果
經過上面的幾步傳統的Java集合操作,我們終於得到了想要的資料。現在我們要輸出前三名。
int i = 1;
for (Girl g : girlTemp) {
if(i>=3){
break;
}
System.out.println(g.toString());
}
OK,至此我們的程式輸出了篩選的結果。上面的寫法,貌似邏輯很清晰,一步步徐徐漸進。是的,這種傳統的寫法,Java程式設計師們已經樂呵呵的寫了很多年了。
一看這個程式碼足足有20多行!可是實現的邏輯並沒有太複雜啊?過陣子你回頭看這個程式碼的話,你多半忘記了這麼一大段程式碼是幹嘛的。如果有註釋還好,你大概掃一一眼能幫助你快速理清程式碼做了啥。如果沒有註釋,你需要逐行去讀完這20多行程式碼,才能明白其邏輯。
Java8 Stream API的寫法
這裡我們在回顧一下,我們的目標:從一個girlList中找出:身高>=162 並且 體重<=53的女孩,然後按顏值排序前三名。Java8的程式碼如下:
List<Girl> girlList = initGirlList();
girlList.stream()
.filter( g -> g.getHeight() >= 162 && g.getWeight() <= 53)
.distinct()
.sorted(Comparator.comparing(Girl::getScore).reversed())
.limit(3)
.forEach( g -> System.out.println(g.toString()));
程式碼6行!並且即使不瞭解Stream API,且你第一次看這個程式碼也能猜出是什麼意思,filter-過濾,distinct-去重,sort-排序,limit-限制條數,forEach-遍歷,就這麼簡單。
結語
Java 這麼老語言,如今都Java13了,然而,最具影響的版本我認為還是Java8。我上學那會兒,學校用Java6的寫法教學。工作之後開始寫Java7的try-with-resource
、鑽石語法等。一直到現在,市面上很多專案都是Java7。有一次有同事給我說他在前公司寫Java8被專案經理說了一頓,我問為啥。他說因為專案經理認為寫Java7好維護,團隊人人都會寫Java7,寫Java8的人不多……無語凝噎。
如果你還沒用上Java8,但願本文中的小例子已經成功的勾起了你用上Java8的興致。問卷:你現在使用的版本是多少?