JAVA 8 主要新特性 ----------------(六)集合Stream API
一、簡介Stream
Java8中有兩大最為重要的改變。第一個是 Lambda 表示式;另外一 個則是 Stream API(java.util.stream.*)。Stream 是 Java8 中處理集合的關鍵抽象概念,它可以指定你希望對集合進行的操作,可以執行非常複雜的查詢、過濾和對映資料等操作。使用Stream API 對集合資料進行操作,就類似於使用 SQL 執行的數據庫查詢。也可以使用 Stream API 來並行執行操作。簡而言之,Stream API 提供了一種高效且易於使用的處理資料的方式。
二、什麼是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);
案例:
容器中過濾資料. 程式碼:點選這裡