強大的 Stream API
一、Stream API 的概述
- Stream到底是什么呢?
是資料渠道,用于操作資料源(集合、陣列等)所生成的元素序列,
“集合講的是資料,Stream講的是計算!”
注意:
- Stream 自己不會存盤元素,
- Stream 不會改變源物件,相反,他們會回傳一個持有結果的新Stream,
- Stream 操作是延遲執行的,這意味著他們會等到需要結果的時候才執行,
- Stream 的操作三個步驟
- 創建 Stream
一個資料源(如:集合、陣列),獲取一個流 - 中間操作
一個中間操作鏈,對資料源的資料進行處理 - 終止操作(終端操作)
一旦執行終止操作,就執行中間操作鏈,并產生結果,之后,不會再被使用
二、Stream API 的創建
- 創建 Stream方式一:通過集合
Java8 中的 Collection 介面被擴展,提供了兩個獲取流的方法:
- default Stream< E > stream() : 回傳一個順序流
- default Stream< E > parallelStream() : 回傳一個并行流
public class testStream {
@Test
public void test() {
List<String> list = new ArrayList();
list.add("張三");
list.add("李四");
Stream<String> stream = list.stream(); //獲取串行流
Stream<String> stream1 = list.parallelStream(); //獲取并行流
//終止操作,列印流,
stream.forEach(System.out::println);
stream.forEach(Sustem.out::println);
}
}
- 創建 Stream方式二:通過陣列
Java8 中的 Arrays 的靜態方法 stream() 可以獲取陣列流:
- static < T > Stream< T > stream(T[] array): 回傳一個流
public class testStream {
@Test
public void test() {
int[] emps = new int[]{1, 2, 3, 4, 5, 6}; //創建陣列
IntStream stream = Arrays.stream(emps);
//終止操作,列印流,
stream.forEach(System.out::println);
}
}
- 創建 Stream方式三:通過Stream的of()
可以呼叫Stream類靜態方法 of()方法, 通過顯示值創建一個流,它可以接收任意數量的引數,
- public static< T > Stream< T > of(T... values) : 回傳一個流
public class testStream {
@Test
public void test() {
Stream<String> stream = Stream.of("a","b","c");
//終止操作,列印流,
stream.forEach(System.out::println);
}
}
- 創建 Stream方式四:創建無限流
可以使用靜態方法 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)
public class testStream {
@Test
public void test() {
//生成
Stream<Double> stream = Stream.generate(Math::random);
//終止操作,打前 10 個印流,
stream.limit(10).forEach(System.out::println);
//迭代
Stream<Integer> stream1 = Stream.iterate(0,(x) -> x + 2);
//終止操作,打前 10 個印流,
stream1.limit(10).forEach(System.out::println);
}
}
二、Stream API 的中間操作
多個中間操作可以連接起來形成一個流水線,除非流水線上觸發終止操作,否則中間操作不會執行任何的處理!而在終止操作時一次性全部處理,稱為“惰性求值”,
- 篩選與切片
| 方 法 | 描 述 |
|---|---|
| filter(Predicate p) | 接收 Lambda , 從流中排除某些元素 |
| distinct() | 篩選,通過流所生成元素的 hashCode() 和 equals() 去除重復元素 |
| limit(long maxSize) | 截斷流,使其元素不超過給定數量 |
| skip(long n) | 跳過元素,回傳一個扔掉了前 n 個元素的流,若流中元素不足 n 個,則回傳一個空流,與 limit(n) 互補 |
@Test
public void test() {
//迭代,創建無限流
Stream<Integer> stream = Stream.iterate(0,(x) -> x + 2);
//獲取大于4的數
Stream<Integer> stream1 = stream.filter((x) -> x > 4);
//獲取大于4中的前10個數
Stream<Integer> stream2 = stream1.limit(10);
//舍棄前5個數
Stream<Integer> stream3 = stream2.skip(5);
//終止操作
stream3.forEach(System.out::println);
}
- 映射
| 方法 | 描述 |
|---|---|
| map(Function f) | 接收一個函式作為引數,該函式會被應用到每個元素上,并將其映射成一個新的元素, |
| mapToDouble(ToDoubleFunction f) | 接收一個函式作為引數,該函式會被應用到每個元素上,產生一個新的 DoubleStream, |
| mapToInt(ToIntFunction f) | 接收一個函式作為引數,該函式會被應用到每個元素上,產生一個新的 IntStream, |
| mapToLong(ToLongFunction f) | 接收一個函式作為引數,該函式會被應用到每個元素上,產生一個新的 LongStream |
| flatMap(Function f) | 接收一個函式作為引數,將流中的每個值都換成另一個流,然后把所有流連接成一個流 |
- 排序
| 方法 | 描述 |
|---|---|
| sorted() | 產生一個新流,其中按自然順序排序 |
| sorted(Comparator com) | 產生一個新流,其中按比較器順序排序 |
Stream API 的終止操作
- 終端操作會從流的流水線生成結果,其結果可以是任何不是流的值,例如: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 |
備注: map 和 reduce 的連接通常稱為 map-reduce 模式,因 Google
用它來進行網路搜索而出名,
- 收集
| 方法 | 描述 |
|---|---|
| collect(Collector c) | 將流轉換為其他形式,接收一個 Collector 介面的實作,用于給Stream中元素做匯總的方法 |
Collector 介面中方法的實作決定了如何對流執行收集的操作(如收集到 List、Set、Map),
另外, Collectors 實用類提供了很多靜態方法,可以方便地創建常見收集器實體,具體方法與實體如下表:
| 方法 | 回傳型別 | 作用 | 呼叫 |
|---|---|---|---|
| toList | List |
把流中元素收集到List | List |
| toSet | Set |
把流中元素收集到Set | Set |
| toCollection | Collection |
把流中元素收集到創建的集合 | Collection |
| counting | Long | 計算流中元素的個數 | long count = list.stream().collect(Collectors.counting()); |
| summingInt | Integer | 對流中元素的整數屬性求和 | int |
| averagingInt | Double | 計算流中元素Integer屬性的平均值 | double avg = list.stream().collect(Collectors.averagingInt(Employee::getSalary)); |
| summarizingInt | IntSummaryStatistics | 收集流中Integer屬性的統計值,如:平均值 | int SummaryStatisticsiss= list.stream().collect(Collectors.summarizingInt(Employee::getSalary)); |
| joining | String | 連接流中每個字串 | String str= list.stream().map(Employee::getName).collect(Collectors.joining()); |
| maxBy | Optional |
根據比較器選擇最大值 | Optional |
| minBy | Optional |
根據比較器選擇最小值 | Optional |
| reducing | 歸約產生的型別 | 從一個作為累加器的初始值開始,利用BinaryOperator與流中元素逐個結合,從而歸約成單個值 | int total=list.stream().collect(Collectors.reducing(0, Employee::getSalar,Integer::sum)); |
| collectingAndThen | 轉換函式回傳的型別 | 包裹另一個收集器,對其結果轉換函式 | int how= list.stream().collect(Collectors.collectingAndThen(Collectors.toList(), List::size)); |
| groupingBy | Map<K, List |
根據某屬性值對流分組,屬性為K,結果為V | Map<Emp.Status, List |
| partitioningBy | Map<Boolean, List |
根據true或false進行磁區 | Map<Boolean,List |
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/518817.html
標籤:Java
上一篇:再有人說synchronized是重量級鎖,就把這篇文章扔給他看
下一篇:為什么方法斷點那么慢
