java8新特性(四)_Stream詳解


之前寫過一篇用stream處理map的文章,但是對stream沒有一個整體的認識,這次結合並發編程網和ibm中介紹stream的文章進行一個總結,我會着重寫對list的處理,畢竟實際工作中大家每天進行使用

Stream簡單介紹

定義

  • A sequence of elements supporting sequential and parallel aggregate operations.

  • 支持順序並行聚合操作的元素序列

看看大神們怎么解讀的

大家可以把Stream當成一個高級版本的Iterator。原始版本的Iterator,用戶只能一個一個的遍歷元素並對其執行某些操作;高級版本的Stream,用戶只要給出需要對其包含的元素執行什么操作,比如“過濾掉長度大於10的字符串”、“獲取每個字符串的首字母”等,具體這些操作如何應用到每個元素上,就給Stream就好了

簡單demo

寫一個過濾null的簡單功能
    public static void main(String[] args) {

        List arrys = Arrays.asList(1, null, 3, 4);
        arrys.forEach(System.out::print);
        System.out.println();
        arrys = (List) arrys.stream()
                .filter(num -> num != null)
                .collect(Collectors.toList());
        arrys.forEach(System.out::print);

    }

執行結果

1null34
134
解析代碼


1、 創建Stream;
2、 轉換Stream(處理數據),每次轉換原有Stream對象不改變,返回一個新的Stream對象(可以有多次轉換);
3、 對Stream進行聚合(Reduce)操作,獲取想要的結果;

創建Stream

最常用的創建Stream有兩種途徑:

  • 通過Stream接口的靜態工廠方法
  • 通過Collection接口的默認方法–stream(),把一個Collection對象轉換成Stream(之前寫的文章對於map的處理就是基於這個)
// 1. Individual values
Stream stream = Stream.of("a", "b", "c");
// 2. Arrays
String [] strArray = new String[] {"a", "b", "c"};
stream = Stream.of(strArray);
stream = Arrays.stream(strArray);
// 3. Collections(實際工作中經常用到)
List<String> list = Arrays.asList(strArray);
stream = list.stream();

轉換Stream方法詳解

這里其實是大家常用到的,着重講解這里,這里的圖片來自並發編程網,不得不佩服,程序寫的好,畫圖也比我畫的好

distinct

distinct: 對於Stream中包含的元素進行去重操作(去重邏輯依賴元素的equals方法),新生成的Stream中沒有重復的元素;

示意圖

代碼演示
    public static void main(String[] args) {

        List<String> list = Arrays.asList("java---", "java---", "erlang---", "lua---", "lua---");
        list.forEach(System.out::print);
        System.out.println();
        list = list.stream()
                .distinct()
                .collect(Collectors.toList());
        list.forEach(System.out::print);

    }

結果

java---java---erlang---lua---lua---
java---erlang---lua---

filter

filter: 對於Stream中包含的元素使用給定的過濾函數進行過濾操作,新生成的Stream只包含符合條件的元素;

示意圖

代碼演示
    public static void main(String[] args) {

        List<String> list = Arrays.asList("java---", "java---", "erlang---", "lua---", "lua---");
        list.forEach(System.out::print);
        System.out.println();
        list = list.stream()
                .filter(e -> e.length() > 7)
                .collect(Collectors.toList());
        list.forEach(System.out::print);

    }

結果

java---java---erlang---lua---lua---
erlang---

map

map:它的作用就是把 input Stream 的每一個元素,映射成 output Stream 的另外一個元素。

示意圖

代碼演示
    public static void main(String[] args) {

        List<String> list = Arrays.asList("java---", "java---", "erlang---", "lua---", "lua---");
        list.forEach(System.out::print);
        System.out.println();
        list = list.stream()
                .map(String::toUpperCase)
                .collect(Collectors.toList());
        list.forEach(System.out::print);

    }

結果

java---java---erlang---lua---lua---
JAVA---JAVA---ERLANG---LUA---LUA---

limit

limit: 對一個Stream進行截斷操作,獲取其前N個元素,如果原Stream中包含的元素個數小於N,那就獲取其所有的元素;

示意圖

代碼演示
    public static void main(String[] args) {

        List<String> list = Arrays.asList("java---", "java---", "erlang---", "lua---", "lua---");
        list.forEach(System.out::print);
        System.out.println();
        list = list.stream()
                .limit(3)
                .collect(Collectors.toList());
        list.forEach(System.out::print);

    }

結果

java---java---erlang---lua---lua---
java---java---erlang---

skip

skip:返回一個丟棄原Stream的前N個元素后剩下元素組成的新Stream,如果原Stream中包含的元素個數小於N,那么返回空Stream;

示意圖

代碼演示
    public static void main(String[] args) {

        List<String> list = Arrays.asList("java---", "java---", "erlang---", "lua---", "lua---");
        list.forEach(System.out::print);
        System.out.println();
        list = list.stream()
                .skip(3)
                .collect(Collectors.toList());
        list.forEach(System.out::print);

    }

結果

java---java---erlang---lua---lua---
lua---lua---

findFirst

findFirst:它總是返回 Stream 的第一個元素,或者空。這里比較重點的是它的返回值類型:Optional

示意圖

代碼演示
    public static void main(String[] args) {

        List<String> list = Arrays.asList("java---", "java---", "erlang---", "lua---", "lua---");
        list.forEach(System.out::print);
        System.out.println();
        Optional<String> first = list.stream()
                .findFirst();

        System.out.println(first.get());

    }

結果

java---java---erlang---lua---lua---
java---

總結

當然,還有很多方法,這里不一一介紹,現實工作中使用常常結合起來

比如這段代碼就是之前文章 過濾map 中 null值和空串的例子

public static Map<String, Object> parseMapForFilterByOptional(Map<String, Object> map) {

        return Optional.ofNullable(map).map(
                (v) -> {
                    Map params = v.entrySet().stream()
                            .filter((e) -> checkValue(e.getValue()))
                            .collect(Collectors.toMap(
                                    (e) -> (String) e.getKey(),
                                    (e) -> e.getValue()
                            ));

                    return params;
                }
        ).orElse(null);
    }

總之,Stream 的特性可以歸納為:

不是數據結構

  • 它沒有內部存儲,它只是用操作管道從 source(數據結構、數組、generator function、IO channel)抓取數據。
  • 它也絕不修改自己所封裝的底層數據結構的數據。例如 Stream 的 filter 操作會產生一個不包含被過濾元素的新 Stream,而不是從 source 刪除那些元素。
  • 所有 Stream 的操作必須以 lambda 表達式為參數

參考文章
-[1.]https://ifeve.com/stream/
-[2.]https://www.ibm.com/developerworks/cn/java/j-lo-java8streamapi/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM