日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) >

java 8 stream()

發(fā)布時(shí)間:2025/3/21 18 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java 8 stream() 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

2019獨(dú)角獸企業(yè)重金招聘Python工程師標(biāo)準(zhǔn)>>>

1. 流的基本概念

1.1 什么是流?

流是Java8引入的全新概念,它用來(lái)處理集合中的數(shù)據(jù),暫且可以把它理解為一種高級(jí)集合。

眾所周知,集合操作非常麻煩,若要對(duì)集合進(jìn)行篩選、投影,需要寫大量的代碼,而流是以聲明的形式操作集合,它就像SQL語(yǔ)句,我們只需告訴流需要對(duì)集合進(jìn)行什么操作,它就會(huì)自動(dòng)進(jìn)行操作,并將執(zhí)行結(jié)果交給你,無(wú)需我們自己手寫代碼。

因此,流的集合操作對(duì)我們來(lái)說(shuō)是透明的,我們只需向流下達(dá)命令,它就會(huì)自動(dòng)把我們想要的結(jié)果給我們。由于操作過(guò)程完全由Java處理,因此它可以根據(jù)當(dāng)前硬件環(huán)境選擇最優(yōu)的方法處理,我們也無(wú)需編寫復(fù)雜又容易出錯(cuò)的多線程代碼了。

1.2 流的特點(diǎn)

1.只能遍歷一次?
我們可以把流想象成一條流水線,流水線的源頭是我們的數(shù)據(jù)源(一個(gè)集合),數(shù)據(jù)源中的元素依次被輸送到流水線上,我們可以在流水線上對(duì)元素進(jìn)行各種操作。一旦元素走到了流水線的另一頭,那么這些元素就被“消費(fèi)掉了”,我們無(wú)法再對(duì)這個(gè)流進(jìn)行操作。當(dāng)然,我們可以從數(shù)據(jù)源那里再獲得一個(gè)新的流重新遍歷一遍。

2.采用內(nèi)部迭代方式?
若要對(duì)集合進(jìn)行處理,則需我們手寫處理代碼,這就叫做外部迭代。而要對(duì)流進(jìn)行處理,我們只需告訴流我們需要什么結(jié)果,處理過(guò)程由流自行完成,這就稱為內(nèi)部迭代。

1.3 流的操作種類

流的操作分為兩種,分別為中間操作 和 終端操作。

1.中間操作?
當(dāng)數(shù)據(jù)源中的數(shù)據(jù)上了流水線后,這個(gè)過(guò)程對(duì)數(shù)據(jù)進(jìn)行的所有操作都稱為“中間操作”。?
中間操作仍然會(huì)返回一個(gè)流對(duì)象,因此多個(gè)中間操作可以串連起來(lái)形成一個(gè)流水線。

2.終端操作?
當(dāng)所有的中間操作完成后,若要將數(shù)據(jù)從流水線上拿下來(lái),則需要執(zhí)行終端操作。?
終端操作將返回一個(gè)執(zhí)行結(jié)果,這就是你想要的數(shù)據(jù)。

1.4 流的操作過(guò)程

使用流一共需要三步:

1.?準(zhǔn)備一個(gè)數(shù)據(jù)源

2.?執(zhí)行中間操作?
中間操作可以有多個(gè),它們可以串連起來(lái)形成流水線。

3.?執(zhí)行終端操作?
執(zhí)行終端操作后本次流結(jié)束,你將獲得一個(gè)執(zhí)行結(jié)果。

2. 流的使用

2.1 獲取流

在使用流之前,首先需要擁有一個(gè)數(shù)據(jù)源,并通過(guò)StreamAPI提供的一些方法獲取該數(shù)據(jù)源的流對(duì)象。數(shù)據(jù)源可以有多種形式:

1.?集合?
這種數(shù)據(jù)源較為常用,通過(guò)stream()方法即可獲取流對(duì)象:

List<Person> list?= new?ArrayList<Person>();Stream<Person> stream = list.stream();

1.?數(shù)組?
通過(guò)Arrays類提供的靜態(tài)函數(shù)stream()獲取數(shù)組的流對(duì)象:

String[] names = {"chaimm","peter","john"};Stream<String> stream = Arrays.stream(names);

1.?值?
直接將幾個(gè)值變成流對(duì)象:

Stream<String> stream = Stream.of("chaimm","peter","john");

1.?文件?

try(Stream lines = Files.lines(Paths.get(“文件路徑名”),Charset.defaultCharset())){? //可對(duì)lines做一些操作? }catch(IOException e){? }?


PS:Java7簡(jiǎn)化了IO操作,把打開IO操作放在try后的括號(hào)中即可省略關(guān)閉IO的代碼。

2.2 篩選filter

filter函數(shù)接收一個(gè)Lambda表達(dá)式作為參數(shù),該表達(dá)式返回boolean,在執(zhí)行過(guò)程中,流將元素逐一輸送給filter,并篩選出執(zhí)行結(jié)果為true的元素。?
如,篩選出所有學(xué)生:

List<Person> result = list.stream().filter(Person::isStudent).collect(toList());

2.3 去重distinct

去掉重復(fù)的結(jié)果:

List<Person> result = list.stream().distinct().collect(toList());

2.4 截取

截取流的前N個(gè)元素:

List<Person> result = list.stream().limit(3).collect(toList());

2.5 跳過(guò)

跳過(guò)流的前n個(gè)元素:

List<Person> result = list.stream().skip(3).collect(toList());

2.6 映射

對(duì)流中的每個(gè)元素執(zhí)行一個(gè)函數(shù),使得元素轉(zhuǎn)換成另一種類型輸出。流會(huì)將每一個(gè)元素輸送給map函數(shù),并執(zhí)行map中的Lambda表達(dá)式,最后將執(zhí)行結(jié)果存入一個(gè)新的流中。?
如,獲取每個(gè)人的姓名(實(shí)則是將Perosn類型轉(zhuǎn)換成String類型):

List<Person>?result =?list.stream().map(Person::getName).collect(toList());

2.7 合并多個(gè)流

例:列出List中各不相同的單詞,List集合如下:

List<String>?list?=?new?ArrayList<String>();list.add("I am a boy");list.add("I love the girl");list.add("But the girl loves another girl");

思路如下:

·?首先將list變成流:

list.stream();

·?按空格分詞:

list.stream().map(line->line.split(" "));

分完詞之后,每個(gè)元素變成了一個(gè)String[]數(shù)組。

·?將每個(gè)String[]變成流:

list.stream().map(line->line.split(" ")).map(Arrays::stream)

此時(shí)一個(gè)大流里面包含了一個(gè)個(gè)小流,我們需要將這些小流合并成一個(gè)流。

·?將小流合并成一個(gè)大流:?
用flatmap替換剛才的map

list.stream().map(line->line.split(" ")).flatmap(Arrays::stream)

·?去重

list.stream().map(line->line.split(" ")).flatmap(Arrays::stream).distinct().collect(toList());

2.8 是否匹配任一元素:anyMatch

anyMatch用于判斷流中是否存在至少一個(gè)元素滿足指定的條件,這個(gè)判斷條件通過(guò)Lambda表達(dá)式傳遞給anyMatch,執(zhí)行結(jié)果為boolean類型。?
如,判斷l(xiāng)ist中是否有學(xué)生:

boolean?result?= list.stream().anyMatch(Person::isStudent);

2.9 是否匹配所有元素:allMatch

allMatch用于判斷流中的所有元素是否都滿足指定條件,這個(gè)判斷條件通過(guò)Lambda表達(dá)式傳遞給anyMatch,執(zhí)行結(jié)果為boolean類型。?
如,判斷是否所有人都是學(xué)生:

boolean?result?= list.stream().allMatch(Person::isStudent);

2.10 是否未匹配所有元素:noneMatch

noneMatch與allMatch恰恰相反,它用于判斷流中的所有元素是否都不滿足指定條件:

boolean?result?= list.stream().noneMatch(Person::isStudent);

2.11 獲取任一元素findAny

findAny能夠從流中隨便選一個(gè)元素出來(lái),它返回一個(gè)Optional類型的元素。

Optional<Person> person = list.stream().findAny();

Optional介紹

Optional是Java8新加入的一個(gè)容器,這個(gè)容器只存1個(gè)或0個(gè)元素,它用于防止出現(xiàn)NullpointException,它提供如下方法:

·?isPresent()?


判斷容器中是否有值。

·?ifPresent(Consume lambda)?


容器若不為空則執(zhí)行括號(hào)中的Lambda表達(dá)式。

·?T get()?


獲取容器中的元素,若容器為空則拋出NoSuchElement異常。

·?T orElse(T other)?


獲取容器中的元素,若容器為空則返回括號(hào)中的默認(rèn)值。

2.12 獲取第一個(gè)元素findFirst

Optional<Person> person = list.stream().findFirst();

2.13 歸約

歸約是將集合中的所有元素經(jīng)過(guò)指定運(yùn)算,折疊成一個(gè)元素輸出,如:求最值、平均數(shù)等,這些操作都是將一個(gè)集合的元素折疊成一個(gè)元素輸出。

在流中,reduce函數(shù)能實(shí)現(xiàn)歸約。?
reduce函數(shù)接收兩個(gè)參數(shù):

·?初始值

·?進(jìn)行歸約操作的Lambda表達(dá)式

2.13.1 元素求和:自定義Lambda表達(dá)式實(shí)現(xiàn)求和

例:計(jì)算所有人的年齡總和

int age = list.stream().reduce(0, (person1,person2)->person1.getAge()+person2.getAge());

reduce的第一個(gè)參數(shù)表示初試值為0;?
reduce的第二個(gè)參數(shù)為需要進(jìn)行的歸約操作,它接收一個(gè)擁有兩個(gè)參數(shù)的Lambda表達(dá)式,reduce會(huì)把流中的元素兩兩輸給Lambda表達(dá)式,最后將計(jì)算出累加之和。

2.13.2 元素求和:使用Integer.sum函數(shù)求和

上面的方法中我們自己定義了Lambda表達(dá)式實(shí)現(xiàn)求和運(yùn)算,如果當(dāng)前流的元素為數(shù)值類型,那么可以使用Integer提供了sum函數(shù)代替自定義的Lambda表達(dá)式,如:

int age =?list.stream().reduce(0, Integer::sum);

Integer類還提供了min、max等一系列數(shù)值操作,當(dāng)流中元素為數(shù)值類型時(shí)可以直接使用。

2.14 數(shù)值流的使用

采用reduce進(jìn)行數(shù)值操作會(huì)涉及到基本數(shù)值類型和引用數(shù)值類型之間的裝箱、拆箱操作,因此效率較低。?
當(dāng)流操作為純數(shù)值操作時(shí),使用數(shù)值流能獲得較高的效率。

2.14.1 將普通流轉(zhuǎn)換成數(shù)值流

StreamAPI提供了三種數(shù)值流:IntStream、DoubleStream、LongStream,也提供了將普通流轉(zhuǎn)換成數(shù)值流的三種方法:mapToInt、mapToDouble、mapToLong。?
如,將Person中的age轉(zhuǎn)換成數(shù)值流:

IntStream stream = list.stream().mapToInt(Person::getAge);

2.14.2 數(shù)值計(jì)算

每種數(shù)值流都提供了數(shù)值計(jì)算函數(shù),如max、min、sum等。?
如,找出最大的年齡:

OptionalInt maxAge = list.stream().mapToInt(Person::getAge).max();

由于數(shù)值流可能為空,并且給空的數(shù)值流計(jì)算最大值是沒有意義的,因此max函數(shù)返回OptionalInt,它是Optional的一個(gè)子類,能夠判斷流是否為空,并對(duì)流為空的情況作相應(yīng)的處理。?
此外,mapToInt、mapToDouble、mapToLong進(jìn)行數(shù)值操作后的返回結(jié)果分別為:OptionalInt、OptionalDouble、OptionalLong

?

轉(zhuǎn)載于:https://my.oschina.net/Cubicluo/blog/1606411

總結(jié)

以上是生活随笔為你收集整理的java 8 stream()的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。