天天看點

Java8 Stream API介紹

stream api是java8中處理集合的關鍵元件,提供了各種豐富的函數式操作

任何集合都可以轉換為stream:

stream的使用分為兩種類型:

intermediate,一個stream可以調用0到多個intermediate類型操作,每次調用會對stream做一定的處理,傳回一個新的stream,這類操作都是惰性化的(lazy),就是說,并沒有真正開始流的周遊。

terminal,一個stream隻能執行一次terminal 操作,而且隻能是最後一個操作,執行terminal操作之後,stream就被消費掉了,并且産生一個結果。

常用操作:foreach、 foreachordered、 toarray、 reduce、 collect、 min、 max、 count、 anymatch、 allmatch、 nonematch、 findfirst、 findany

使用示例:

collect操作主要用于将stream中的元素收集到一個集合容器中,collect函數的定義如下:

第一個參數supplier用于生成一個目标集合容器類型的執行個體;

函數biconsumer用于處理t和u這兩個類型的資料,用在此處,第二個參數表示biconsumer表示處理集合類型r以及集合元素類型t,即将t添加到r中;

相應的第三個參數biconsumer則表示将集合類型r和另一個r做合并操作;

執行個體如下:

以上寫法可以使用操作符“::”簡化,文法如下:

對象::執行個體方法

類::靜态方法

類::執行個體方法

java.util.stream.collectors類中已經預定義好了tolist,toset,tomap,tocollection等友善使用的方法,是以以上代碼還可以簡化如下:

将結果收集到map中,collectors.tomap方法的兩個重載定義如下:

keymapper函數用于從執行個體t中得到一個k類型的map key;

valuemapper函數用于從執行個體t中得到一個u類型的map value;

mergefunction函數用于處理key沖突的情況,預設為throwingmerger(),抛出illegalstateexception異常;

mapsupplier函數用于生成一個map執行個體;

假設有一個user實體類,有方法getid(),getname(),getage()等方法,現在想要将user類型的流收集到一個map中,示例如下:

假設要得到按年齡分組的map>,可以按這樣寫:

這種寫法雖然可以實作分組功能,但是太過繁瑣,好在collectors中提供了groupingby方法,可以用來實作該功能,簡化後寫法如下:

類似的,collectors中還提供了partitioningby方法,接受一個predicate函數,該函數傳回boolean值,用于将内容分為兩組。假設user實體中包含性别資訊getsex(),可以按如下寫法将userstream按性别分組:

collectors中還提供了一些對分組後的元素進行downstream處理的方法:

counting方法傳回所收集元素的總數;

summing方法會對元素求和;

maxby和minby會接受一個比較器,求最大值,最小值;

mapping函數會應用到downstream結果上,并需要和其他函數配合使用;

以上為各種collectors操作的使用案例。

optional 是對t類型對象的封裝,它不會傳回null,因而使用起來更加安全。

ifpresent方法接受一個函數作為形參,如果存在目前optinal存在值則使用目前值調用函數,否則不做任何操作,示例如下:

orelse方法,orelseget方法,當值不存在時産生一個替代值,示例如下:

steam.filter方法接受一個predicate函數作為入參,該函數傳回一個boolean類型,下圖為stream和collectors方法參數的函數式接口:

Java8 Stream API介紹

stream的處理總會在最後的terminal操作才會真正執行;

沒有内部存儲,也不能改變使用到的資料源,每次操作都會生成一個新的流;

并行流使用fork/join 池來實作,對于非cpu密集型任務,需要謹慎使用;

相對于循環周遊操作代碼可讀性更高;