首頁 >Java >java教程 >分析Java Stream API中的終端機操作範例

分析Java Stream API中的終端機操作範例

王林
王林轉載
2023-05-08 17:34:17932瀏覽

    一、Java Stream管道資料處理作業

    在本號之前寫過的文章中,曾經介紹過Java Stream管道流是用於簡化集合類別元素處理的java API。在使用的過程中分為三個階段。在開始本文之前,我覺得仍然需要給一些新朋友介紹一下這三個階段,如圖:

    分析Java Stream API中的終端機操作範例

    • #第一階段(圖中藍色):將集合、陣列、或行文字檔案轉換為java Stream管道流

    • #第二階段(圖中虛線部分):管道流式資料處理操作,處理管道中的每一個元素。上一個管道中的輸出元素作為下一個管道的輸入元素。

    • 第三階段(圖中綠色):管道流程結果處理操作,也就是本文的將要介紹的核心內容。

    在開始學習之前,仍然有必要回顧一下我們之前給大家講過的一個例子:

    List<String> nameStrs = Arrays.asList("Monkey", "Lion", "Giraffe","Lemur");
    List<String> list = nameStrs.stream()
            .filter(s -> s.startsWith("L"))
            .map(String::toUpperCase)
            .sorted()
            .collect(toList());
    System.out.println(list);

    首先使用stream()方法將字串List轉換為管道流Stream

    然後進行管道資料處理操作,先用fliter函數過濾所有大寫L開頭的字串,然後將管道中的字串轉換為大寫字母toUpperCase,然後呼叫sorted方法排序。這些API的用法在本號之前的文章有介紹過。其中也使用到了lambda表達式和函數參考。

    最後使用collect函數進行結果處理,將java Stream管道流轉換為List。最終list的輸出結果是:[LEMUR, LION]

    如果你不使用java Stream管道流的話,想想你需要多少行程式碼完成上面的功能呢?回到正題,這篇文章就是要跟大家介紹第三階段:管道流處理結果都可以做哪些操作呢?下面開始吧!

    二、ForEach和ForEachOrdered

    如果我們只是希望將Stream管道流的處理結果列印出來,而不是進行類型轉換,我們就可以使用forEach()方法或forEachOrdered()方法。

    Stream.of("Monkey", "Lion", "Giraffe", "Lemur", "Lion")
            .parallel()
            .forEach(System.out::println);
    Stream.of("Monkey", "Lion", "Giraffe", "Lemur", "Lion")
            .parallel()
            .forEachOrdered(System.out::println);

    parallel()函數表示對管道中的元素進行並行處理,而不是串行處理,這樣處理速度就更快。但是這樣就有可能導致管道流中後面的元素先處理,前面的元素後處理,也就是元素的順序無法保證

    forEachOrdered從名字上看就可以理解,雖然在數據處理順序上可能無法保障,但是forEachOrdered方法可以在元素輸出的順序上保證與元素進入管道流的順序一致。也就是下面的樣子(forEach方法則無法保證這個順序):

    Monkey
    Lion
    Giraffe
    Lemur
    Lion

    三、元素的收集collect

    java Stream 最常見的用法就是:一將集合類別轉換成管道流,二對管道流資料處理,三將管道流處理結果在轉換成集合類別。那麼collect()方法就為我們提供了這樣的功能:將管道流處理結果在轉換成集合類別。

    3.1.收集為Set

    透過Collectors.toSet()方法收集Stream的處理結果,將所有元素收集到Set集合中。

    Set<String> collectToSet = Stream.of(
       "Monkey", "Lion", "Giraffe", "Lemur", "Lion"
    ) 
    .collect(Collectors.toSet());
    //最终collectToSet 中的元素是:[Monkey, Lion, Giraffe, Lemur],注意Set会去重。

    3.2.收集到List

    同樣,可以將元素收集到List使用toList()收集器。

    List<String> collectToList = Stream.of(
       "Monkey", "Lion", "Giraffe", "Lemur", "Lion"
    ).collect(Collectors.toList());
    
    // 最终collectToList中的元素是: [Monkey, Lion, Giraffe, Lemur, Lion]

    3.3.通用的收集方式

    上面為大家介紹的元素收集方式,都是專用的。例如使用Collectors.toSet()收集為Set類型集合;使用Collectors.toList()收集為List類型集合。那麼,有沒有一種比較通用的資料元素收集方式,將資料收集為任意的Collection介面子類型。所以,這裡就像大家介紹一種通用的元素收集方式,你可以將資料元素收集到任意的Collection類型:也就是向所需Collection類型提供建構函數的方式。

    LinkedList<String> collectToCollection = Stream.of(
       "Monkey", "Lion", "Giraffe", "Lemur", "Lion"
    ).collect(Collectors.toCollection(LinkedList::new));
    //最终collectToCollection中的元素是: [Monkey, Lion, Giraffe, Lemur, Lion]

    注意:程式碼中使用了LinkedList::new,實際上是呼叫LinkedList的建構函數,將元素收集到Linked List。當然你也可以使用諸如LinkedHashSet::newPriorityQueue::new將資料元素收集為其他的集合類型,這樣就比較通用了。

    3.4.收集到Array

    透過toArray(String[]::new)方法收集Stream的處理結果,將所有元素收集到字串陣列中。

    String[] toArray = Stream.of(
       "Monkey", "Lion", "Giraffe", "Lemur", "Lion"
    ) .toArray(String[]::new);
    //最终toArray字符串数组中的元素是: [Monkey, Lion, Giraffe, Lemur, Lion]

    3.5.收集到Map

    使用Collectors.toMap()方法將資料元素收集到Map裡面,但是出現一個問題:那就是管道中的元素是作為key,還是作為value。我們用到了一個Function.identity()方法,很簡單就是回傳一個「 t -> t 」(輸入就是輸出的lambda表達式)。另外使用管道流處理函數distinct()來確保Map鍵值的唯一性。

    Map<String, Integer> toMap = Stream.of(
        "Monkey", "Lion", "Giraffe", "Lemur", "Lion"
    )
    .distinct()
    .collect(Collectors.toMap(
           Function.identity(),   //元素输入就是输出,作为key
           s -> (int) s.chars().distinct().count()// 输入元素的不同的字母个数,作为value
    ));
    // 最终toMap的结果是: {Monkey=6, Lion=4, Lemur=5, Giraffe=6}

    3.6.分組收集groupingBy

    Collectors.groupingBy用來實現元素的分組收集,下面的程式碼示範如何根據首字母將不同的資料元素收集到不同的List,並封裝為Map。

    Map<Character, List<String>> groupingByList =  Stream.of(
        "Monkey", "Lion", "Giraffe", "Lemur", "Lion"
    )
    .collect(Collectors.groupingBy(
           s -> s.charAt(0) ,  //根据元素首字母分组,相同的在一组
           // counting()        // 加上这一行代码可以实现分组统计
    ));
    // 最终groupingByList内的元素: {G=[Giraffe], L=[Lion, Lemur, Lion], M=[Monkey]}
    //如果加上counting() ,结果是:  {G=1, L=3, M=1}

    这是该过程的说明:groupingBy第一个参数作为分组条件,第二个参数是子收集器。

    四、其他常用方法

    boolean containsTwo = IntStream.of(1, 2, 3).anyMatch(i -> i == 2);
    // 判断管道中是否包含2,结果是: true
    long nrOfAnimals = Stream.of(
        "Monkey", "Lion", "Giraffe", "Lemur"
    ).count();
    // 管道中元素数据总计结果nrOfAnimals: 4
    int sum = IntStream.of(1, 2, 3).sum();
    // 管道中元素数据累加结果sum: 6
    OptionalDouble average = IntStream.of(1, 2, 3).average();
    //管道中元素数据平均值average: OptionalDouble[2.0]
    int max = IntStream.of(1, 2, 3).max().orElse(0);
    //管道中元素数据最大值max: 3
    IntSummaryStatistics statistics = IntStream.of(1, 2, 3).summaryStatistics();
    // 全面的统计结果statistics: IntSummaryStatistics{count=3, sum=6, min=1, average=2.000000, max=3}

    以上是分析Java Stream API中的終端機操作範例的詳細內容。更多資訊請關注PHP中文網其他相關文章!

    陳述:
    本文轉載於:yisu.com。如有侵權,請聯絡admin@php.cn刪除