1. 程式人生 > >如何用Java8 Stream API找到心儀的女朋友

如何用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的興致。問卷:你現在使用的版本是多少?