Java 8 Stream 使用
轉載請標明出處:http://blog.csdn.net/zhaoyanjun6/article/details/106389071
本文出自【趙彥軍的博客】
目錄
- 1、基礎概念
- 2、常見操作符
- filter 過濾
- findFirst 查找第一個
- sorted 從小到大排序
- map 方法用于映射每個元素到對應的結果
- limit 獲取指定數量的流
- collect 將流轉換成集合和聚合元素
- average 求平均值
- 3、Stream 執行順序
- 例子1
- 例子2
- 4、數據流復用問題
- 5、并行流
- 總結
1、基礎概念
Java 8 API添加了一個新的抽象稱為流Stream,可以讓你以一種聲明的方式處理數據。
Stream 使用一種類似用 SQL 語句從數據庫查詢數據的直觀方式來提供一種對 Java 集合運算和表達的高階抽象。
Stream API可以極大提高Java程序員的生產力,讓程序員寫出高效率、干凈、簡潔的代碼。
這種風格將要處理的元素集合看作一種流, 流在管道中傳輸, 并且可以在管道的節點上進行處理, 比如篩選, 排序,聚合等。
元素流在管道中經過中間操作(intermediate operation)的處理,最后由最終操作(terminal operation)得到前面處理的結果。
如果你用過 rxjava ,入門就很簡單。
2、常見操作符
filter 過濾
var list = mutableListOf("b", "a", "d", "c")ist.stream().filter { it != "a" //輸出元素不是 a 的元素}.forEach {Log.d("yanjun", it)}輸出結果:
D/yanjun: bD/yanjun: dD/yanjun: cfindFirst 查找第一個
var list = mutableListOf("b", "a", "d", "c")var first = list.stream().findFirst() //查找第一個元素.get()Log.d("yanjun", first)輸出結果:
D/yanjun: bsorted 從小到大排序
var list2 = listOf(3, 1, 2)list2.stream().sorted() //默認從小到大排序.forEach {Log.d("yanjun", it.toString())}輸出結果:
D/yanjun: 1D/yanjun: 2D/yanjun: 3map 方法用于映射每個元素到對應的結果
var list = listOf(3, 1, 2)list.stream().map {it * 2 //所有元素都乘以 2 }.forEach {Log.d("yanjun", it.toString())}輸出結果:
D/yanjun: 6D/yanjun: 2D/yanjun: 4limit 獲取指定數量的流
var list = listOf(3, 1, 2)list.stream().limit(2) //只輸出前2個數據.forEach {Log.d("yanjun", it.toString())}輸出結果:
D/yanjun: 3D/yanjun: 1collect 將流轉換成集合和聚合元素
var list = listOf(3, 1, 2)var list2 = list.stream().sorted() //排序 結果為:1 2 3 .collect(Collectors.toList()) //把流數據轉換成 list list2.forEach {Log.d("yanjun", it.toString())}輸出結果:
D/yanjun: 1D/yanjun: 2D/yanjun: 3average 求平均值
var list = listOf(3, 1, 2)var value = list.average() //求平均值Log.d("yanjun", value.toString())輸出結果:
D/yanjun: 2.03、Stream 執行順序
數據流的鏈式調用是垂直執行的, 但并不是每個操作符都是垂直的,sorted是水平執行的。
為什么要設計成這樣呢?原因是出于性能的考慮。
例子1
var list = mutableListOf("b", "a", "d", "c")list.stream().map {Log.d("yanjun map", it)it}.forEach {Log.d("yanjun forEach", it)}輸出結果:
D/yanjun map: b D/yanjun forEach: b D/yanjun map: a D/yanjun forEach: a D/yanjun map: d D/yanjun forEach: d D/yanjun map: c D/yanjun forEach: c例子2
var list = mutableListOf("b", "a", "d", "c")list.stream().map {Log.d("yanjun map", it)it}.sorted() //排序.forEach {Log.d("yanjun forEach", it)}輸出結果:
D/yanjun map: b D/yanjun map: a D/yanjun map: d D/yanjun map: c D/yanjun forEach: a D/yanjun forEach: b D/yanjun forEach: c D/yanjun forEach: d4、數據流復用問題
Java8 Stream 流是不能被復用的,一旦你調用任何終端操作,流就會關閉:
var list = mutableListOf("b", "a", "d", "c")var stream = list.stream()//流第一次被使用,使用完畢后,流被關閉,不能重復使用 stream.forEach {Log.d("yanjun", it) }//流第二次被使用,會報異常 stream.forEach {Log.d("yanjun", it)}報異常,程序出錯
5、并行流
集合支持parallelStream()方法來創建元素的并行流?;蛘吣憧梢栽谝汛嬖诘臄祿魃险{用中間方法parallel(),將串行流轉換為并行流,這也是可以的。
var list = mutableListOf("b", "a", "d", "c")list.parallelStream() //創建并行流.map {Thread.sleep(5000) //模擬耗時操作Log.d("yanjun map", Thread.currentThread().name + " " + it)it}.forEach {Log.d("yanjun forEach", Thread.currentThread().name + " " + it)}輸出結果:
D/yanjun map: main d D/yanjun forEach: main d D/yanjun map: ForkJoinPool.commonPool-worker-1 a D/yanjun map: ForkJoinPool.commonPool-worker-2 b D/yanjun forEach: ForkJoinPool.commonPool-worker-1 a D/yanjun forEach: ForkJoinPool.commonPool-worker-2 b D/yanjun map: ForkJoinPool.commonPool-worker-3 c D/yanjun forEach: ForkJoinPool.commonPool-worker-3 c如您所見,并行流使用了所有的ForkJoinPool中的可用線程來執行流式操作。在持續的運行中,輸出結果可能有所不同,因為所使用的特定線程是非特定的。
總結
- 無存儲:Stream是基于數據源的對象,它本身不存儲數據元素,而是通過管道將數據源的元素傳遞給操作。
- 函數式編程:對Stream的任何修改都不會修改背后的數據源,比如對Stream執行filter操作并不會刪除被過濾的元素,而是會產生一個不包含被過濾元素的新的Stream。
- 延遲執行:Stream的操作由零個或多個中間操作(intermediate operation)和一個結束操作(terminal operation)兩部分組成。只有執行了結束操作,Stream定義的中間操作才會依次執行,這就是Stream的延遲特性。
- 可消費性:Stream只能被“消費”一次,一旦消費就會失效。就像容器的迭代器那樣,想要再次遍歷必須重新生成一個新的Stream。
總結
以上是生活随笔為你收集整理的Java 8 Stream 使用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Android GooglePay 填坑
- 下一篇: Kotlin实战指南十五:协程泄漏