JDK8之lambda處理stream的常用例子

前言

在日常的編碼中,我們經常要對集合類對象進行處理。JDK8之前,我們可能要用for循環等方式來處理集合中的每一個元素。不過JDK8的lambda表達式給了我們更方便的選擇。

關於lambda表達式和stream的介紹,這裏有一篇文章寫得非常好,詳細易懂。JDK 8 函數式編程入門

直接上demo

既然本文是要寫一些常用的例子,那就直接上demo了。

1.先創建一個簡單的實體類

@Data
@Builder
public class DefaultTestBean {
    private int id;
    private String name;
    private String area;
    private double score;
}

2.初始化一個我們要處理的list

private List<DefaultTestBean> initList() {
    List<DefaultTestBean> resultList = Lists.newArrayList();
    resultList.add(DefaultTestBean.builder().id(1).name("小白").area("A").score(10.1).build());
    resultList.add(DefaultTestBean.builder().id(2).name("小紅").area("B").score(9.6).build());
    resultList.add(DefaultTestBean.builder().id(3).name("小黃").area("A").score(5.9).build());
    resultList.add(DefaultTestBean.builder().id(4).name("小藍").area("C").score(3.3).build());
    return resultList;
}

3.開始搞事情,看註釋就好

/**
 * 盤他!
 */
public void showMeHowToUseStream() {
    List<DefaultTestBean> list = initList();
    PrintUtil.printJSONString("initList", list);

    // 1.【轉list】提取list中對象的某個字段,返回list。用map進行類型轉換,用collect(Collectors.toList())返回新的list。
    List<String> nameList = list.stream().map(DefaultTestBean::getName).collect(Collectors.toList());
    PrintUtil.printJSONString("nameList", nameList);

    // 2.【過濾】對某個字段過濾,用filter。只有符合filter中的bean纔會保留下來。
    List<DefaultTestBean> highCoreList = list.stream().filter(bean -> bean.getScore() > 5.0).collect(Collectors.toList());
    PrintUtil.printJSONString("highCoreList", highCoreList);

    // 3.【排序】根據id這個字段返回倒序排序list。如果是a-b,則是升序。如果是b-a,則是倒序。
    List<DefaultTestBean> sortList = list.stream().sorted((a, b) -> b.getId() - a.getId()).collect(Collectors.toList());
    PrintUtil.printJSONString("sortList", sortList);

    // 4.【轉map】list轉成map,key爲id,value爲bean。用Collectors.toMap轉成map。
    Map<Integer, DefaultTestBean> idBeanMap = list.stream().collect(Collectors.toMap(DefaultTestBean::getId, bean -> bean));
    PrintUtil.printJSONString("idBeanMap", idBeanMap);

    // 5.【轉map】提取list中信息轉成map,key爲id,value爲name。同上。
    Map<Integer, String> idNameMap = list.stream().collect(Collectors.toMap(DefaultTestBean::getId, DefaultTestBean::getName));
    PrintUtil.printJSONString("idNameMap", idNameMap);

    // 6.【轉map分組】對list中的bean進行分組,key爲area,value爲list。
    Map<String, List<DefaultTestBean>> areaListMap = list.stream().collect(Collectors.groupingBy(DefaultTestBean::getArea));
    PrintUtil.printJSONString("areaListMap", areaListMap);
}

public static <T> void printJSONString(String title, T t) {
    System.out.println(title + ":" + JSON.toJSONString(t, SerializerFeature.IgnoreNonFieldGetter));
}

執行showMeHowToUseStream方法,我們可以看到以下輸出:

initList:[{"area":"A","id":1,"name":"小白","score":10.1},{"area":"B","id":2,"name":"小紅","score":9.6},{"area":"A","id":3,"name":"小黃","score":5.9},{"area":"C","id":4,"name":"小藍","score":3.3}]

nameList:["小白","小紅","小黃","小藍"]

highCoreList:[{"area":"A","id":1,"name":"小白","score":10.1},{"area":"B","id":2,"name":"小紅","score":9.6},{"area":"A","id":3,"name":"小黃","score":5.9}]

sortList:[{"area":"C","id":4,"name":"小藍","score":3.3},{"area":"A","id":3,"name":"小黃","score":5.9},{"area":"B","id":2,"name":"小紅","score":9.6},{"area":"A","id":1,"name":"小白","score":10.1}]

idBeanMap:{1:{"area":"A","id":1,"name":"小白","score":10.1},2:{"area":"B","id":2,"name":"小紅","score":9.6},3:{"area":"A","id":3,"name":"小黃","score":5.9},4:{"area":"C","id":4,"name":"小藍","score":3.3}}

idNameMap:{1:"小白",2:"小紅",3:"小黃",4:"小藍"}

areaListMap:{"A":[{"area":"A","id":1,"name":"小白","score":10.1},{"area":"A","id":3,"name":"小黃","score":5.9}],"B":[{"area":"B","id":2,"name":"小紅","score":9.6}],"C":[{"area":"C","id":4,"name":"小藍","score":3.3}]}

4.有些小坑

在轉map時,key值需要唯一,否則會報錯。
看demo:

public void trap() {
    List<DefaultTestBean> list = initList();
    // 1.轉map時,key值需要唯一。否則會報錯。
    list.add(DefaultTestBean.builder().id(1).name("白小白").area("A").score(10.1).build());

    // 有重複,報錯:java.lang.IllegalStateException: Duplicate key 小白
    Map<Integer, String> idNameMap = list.stream().collect(Collectors.toMap(DefaultTestBean::getId, DefaultTestBean::getName));
    PrintUtil.printJSONString("idNameMap", idNameMap);

    // 我們可以用Collectors.toMap的重載方法,傳入一個合併函數來決定如何合併相同key的值即可。
    // 我們默認返回list中第一個出現的重複的值
    Map<Integer, String> idNameMap = list.stream().collect(Collectors.toMap(DefaultTestBean::getId, DefaultTestBean::getName, (value1, value2) -> value1));
    PrintUtil.printJSONString("idNameMap", idNameMap);

    // 我們把兩個值按照自己的邏輯合併到一起
    Map<Integer, String> idMergeNameMap = list.stream().collect(Collectors.toMap(DefaultTestBean::getId, DefaultTestBean::getName, (value1, value2) -> value1 + "和" + value2));
    PrintUtil.printJSONString("idMergeNameMap", idMergeNameMap);
    }
}

總結

個人認爲,對於集合類的日常處理,差不多就是這幾種。如果以後發現還會經常用到其他的處理方式,會補充進來的。

其次,自己在想這種把內容直接寫到代碼註釋裏的方式,可讀性如何。因爲我感覺對於一些實用性的文章,還是要多上一些代碼和demo會有更高的價值。所以想着,如果直接把代碼丟上來,然後把文章要解釋的內容以註釋的形式填充到代碼裏,那是不是看完這段代碼就能一次性的接受了內容和實踐效果?之後的文章也可以繼續這樣試一試。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章