1. 程式人生 > >JAVA 8 主要新特性 ----------------(六)集合Stream API

JAVA 8 主要新特性 ----------------(六)集合Stream API

一、簡介Stream

        Java8中有兩大最為重要的改變。第一個是 Lambda 表示式;另外一 個則是 Stream API(java.util.stream.*)。Stream 是 Java8 中處理集合的關鍵抽象概念,它可以指定你希望對集合進行的操作,可以執行非常複雜的查詢、過濾和對映資料等操作。使用Stream API 對集合資料進行操作,就類似於使用 SQL 執行的數據庫查詢。也可以使用 Stream API 來並行執行操作。簡而言之,Stream API 提供了一種高效且易於使用的處理資料的方式。
二、什麼是Stream

         流(Stream) 到底是什麼呢?     
    是資料渠道,用於操作資料來源(集合、陣列等)所生成的元素序列。“集合講的是資料,流講的是計算!”

注意:

  (1)Stream 自己不會儲存元素。
     (2)
Stream 不會改變源物件。相反,他們會返回一個持有結果的新Stream。

     (3)Stream 操作是延遲執行的。這意味著他們會等到需要結果的時候才執行。

三、Stream 的操作三個步驟

No.1 Stream

1、建立 Stream

       一個數據源(如:集合、陣列),獲取一個流

       Java8 中的 Collection 介面被擴充套件,提供了 兩個獲取流的方法:
       
 default Stream<E> stream() : 返回一個順序流 
        default Stream<E> parallelStream() : 返回一個並行流

2、由陣列建立流
         Java8 中的 Arrays 的靜態方法 stream() 可 以獲取陣列流:
       
static <T> Stream<T> stream(T[] array): 返回一個流

過載形式,能夠處理對應基本型別的陣列: 
        public static IntStream stream(int[] array) 

        public static LongStream stream(long[] array) 

        public static DoubleStream stream(double[] array)

3、由值建立流

可以使用靜態方法 Stream.of(), 通過顯示值 建立一個流。它可以接收任意數量的引數。

        public static<T> Stream<T> of(T... values) : 返回一個流

4、由函式建立流:建立無限流

可以使用靜態方法 Stream.iterate() 和 Stream.generate(), 建立無限流。迭代
       public static<T> Stream<T> iterate(final T seed, final UnaryOperator<T> f)

 

生成
public static<T> Stream<T> generate(Supplier<T> s) :

No.2 Stream

 

 

1、中間操作
       一箇中間操作鏈,對資料來源的資料進行處理 

2、Stream 的中間操作
      多箇中間操作可以連線起來形成一個流水線,除非流水 線上觸發終止操作,否則中間操作不會執行任何的處理! 而在終止操作時一次性全部處理,稱為“惰性求值”。

篩選與切片

     

方法 描述
filter(Predicate p) 

接收 Lambda , 從流中排除某些元素。

distinct()   篩選,通過流所生成元素的 hashCode() 和 equals() 去 除重複元素 
limit(long maxSize) 

截斷流,使其元素不超過給定數量。

skip(long n) 

跳過元素,返回一個扔掉了前 n 個元素的流。若流中元素 不足 n 個,則返回一個空流。與 limit(n) 互補

 

容器中map和reduce

 

map案例

 

     (1)案例一:小寫轉大寫

 

                    “test”,“hello”,“world”,“java”,“tom”,“c”,“JavaScript”        程式碼:點選這裡

 

     (2)案例二:元素擴大2倍

 

                    1,2,3,4—>2,4,6,8

 

                   程式碼:點選這裡

對映

       

方法 描述
map(Function f)

接收一個函式作為引數,該函式會被應用到每個元 素上,並將其對映成一個新的元素。

mapToDouble(ToDoubleFunction f)  接收一個函式作為引數,該函式會被應用到每個元 素上,產生一個新的 DoubleStream。 
mapToInt(ToIntFunction f)   接收一個函式作為引數,該函式會被應用到每個元 素上,產生一個新的 IntStream。 
mapToLong(ToLongFunction f) 

接收一個函式作為引數,該函式會被應用到每個元 素上,產生一個新的 LongStream。

flatMap(Function f)   接收一個函式作為引數,將流中的每個值都換成另 一個流,然後把所有流連線成一個流

   

reduce案例:      (1)容器求和                       1,2,3,4資料求和               程式碼:點選這裡   map和reduce總結      (1)map是針對每個資料處理,reduce是針對集合最後處理.      (2)map()進行資料重寫組合,reduce()是對集合中所有資料變為一個結果.        例如: SQL語句的sum\min\max方法功能  

3、排序

方法 描述
sorted() 

產生一個新流,其中按自然順序排序

sorted(Comparator comp)  產生一個新流,其中按比較器順序排序

 

          正序排序: list.stream().sorted()                          --------------------------ASC   倒序排序: list.stream().sorted().reversed()              ------------------------------------DESC   其中sorted中間可以加入引數 list.stream().sorted(Person::getAge)           Comparator使用 正序 list.stream().sorted(Comparator.comparing(Person::getAge))    倒序 list.stream().sorted(Comparator.comparing(Person::getAge).reversed())   No.3 終止操作 1、  終止操作(終端操作)

      一個終止操作,執行中間操作鏈,併產生結果

2、終端操作會從流的流水線生成結果。其結果可以是任何不是流的 值,例如:List、Integer,甚至是 void 。

查詢與匹配

方法 描述
allMatch(Predicate p) 

檢查是否匹配所有元素

anyMatch(Predicate p) 

檢查是否至少匹配一個元素

noneMatch(Predicate p) 

檢查是否沒有匹配所有元素

findFirst()   返回第一個元素
findAny()   返回當前流中的任意元素
count() 

返回流中元素總數

max(Comparator c) 

返回流中最大值

min(Comparator c) 

返回流中最小值

forEach(Consumer c)  內部迭代(使用 Collection 介面需要使用者去做迭 代,稱為外部迭代。相反,Stream API 使用內部 迭代——它幫你把迭代做了)

 

     

 

 

 

 

 

 

 

 

 

 

 

 

 

歸約

reduce(T iden, BinaryOperator b)  可以將流中元素反覆結合起來,得到一個值。 返回 T 
reduce(BinaryOperator b)  可以將流中元素反覆結合起來,得到一個值。 返回 Optional<T> 

備註:

       map 和 reduce 的連線通常稱為 map-reduce 模式,因 Google 用它 來進行網路搜尋而出名。

收集      

方法 描述
collect(Collector c) 

將流轉換為其他形式。接收一個 Collector介面的 實現,用於給Stream中元素做彙總的方法

 

 

 


Collector 介面中方法的實現決定了如何對流執行收集操作(如收
集到 List、Set、Map)。但是 Collectors 實用類提供了很多靜態方法,可以方便地建立常見收集器例項。

 

Consumer

 

      定義:

 

             Consumer<T>代表了接受一個輸入引數並且無返回的操作,如果某一類操作不需要返回介面,可以對該類操作抽取邏輯.

 

      方法:

 

             無返回函式操作void accept(T t);

 

     案例:

 

            遍歷容器forEach()方法         程式碼:點選這裡

 

Predicate

 

     定義:

 

            Predicate函式式介面的主要作用就是提供一個test、

 

方法,接受一個引數返回一個布林型別.

 

     方法:

 

            函式操作boolean test(T t);

 

    案例:

 

            容器中過濾資料.                 程式碼:點選這裡