亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Java?8中?Stream小知識(shí)小技巧方法梳理

 更新時(shí)間:2022年09月01日 08:36:54   作者:寧在春???????  
這篇文章主要介紹了Java8中Stream小知識(shí)小技巧方法梳理,Stream流和迭代器一樣,它只能夠迭代一次。當(dāng)它遍歷完的時(shí)候,我們就稱它已經(jīng)消費(fèi)完了。如果還想重新執(zhí)行操作,那么就只能從原來(lái)的地方再獲取一個(gè)流

前言

上篇只是簡(jiǎn)單的動(dòng)手操作操作了流(stream),那 stream 到底是什么呢?

官方的簡(jiǎn)短定義:從支持?jǐn)?shù)據(jù)處理操作的源生成的元素序列

分成三部分:

  • 元素序列:你可以簡(jiǎn)單將它類比于一樣,不過(guò)集合說(shuō)的是數(shù)據(jù)的集合,而 stream 重點(diǎn)在于表達(dá)計(jì)算。如我們之前說(shuō)到的 filter、map、sorted、limit等等
  • :昨天我提到,如果了解過(guò) Liunx 管道命令的朋友們,會(huì)知道,Liunx 的管道命令中的前一條命令的結(jié)果(輸出流)就是執(zhí)行下一條命令的輸入流。 stream流其實(shí)也是類似的,每次執(zhí)行完一個(gè) filter、sorted 等等它們的返回值也是 stream 流,然后作為下一個(gè)操作的輸入流,這種。
  • 數(shù)據(jù)處理:這里說(shuō)的處理,就是那些filter、map、sorted、limit等。

你可以把它理解為概念上或是形式上的數(shù)據(jù)結(jié)構(gòu),而不是具體的。

只能遍歷的一次 Stream

Stream 流和 迭代器一樣,它只能夠迭代一次

當(dāng)它遍歷完的時(shí)候,我們就稱它已經(jīng)消費(fèi)完了。如果還想重新執(zhí)行操作,那么就只能從原來(lái)的地方再獲取一個(gè)流啦。

?/**
? ? ? * 圖個(gè)樂(lè)子
? ? ? */
?public static List<String> list = Arrays.asList("醫(yī)醫(yī)","一一","花花","菡菡","春春","寧姐","...");
??
?public static void main(String[] args) {
? ? ?Stream<String> stream = list.stream();
? ? ?stream.forEach(System.out::println);
? ? ?stream.forEach(System.out::println);
?}

當(dāng)執(zhí)行第二句stream.forEach(System.out::println);時(shí),會(huì)爆出如下異常:

?Exception in thread "main" java.lang.IllegalStateException: stream has already been operated upon or closed
?    at java.util.stream.AbstractPipeline.sourceStageSpliterator(AbstractPipeline.java:279)
?    at java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:580)
?    at com.nzc.stream02.Stream02Demo.main(Stream02Demo.java:25)

stream has already been operated upon or closed :流已經(jīng)被操作完或者關(guān)閉啦~

那么為什么流只能遍歷一次呢?

我的回答肯定是 Java 中的設(shè)計(jì)是如此。

我們先來(lái)回憶一下我昨天沒(méi)提到的一個(gè)知識(shí)點(diǎn):

隨便舉一個(gè)例子,然后我們將 filter、map、limit、collect 都使用上。

?List<Student> students = new ArrayList<>();
??
?students.add(new Student("學(xué)生A", "大學(xué)1", 18, 98.0));
?students.add(new Student("學(xué)生A", "大學(xué)1", 18, 91.0));
?students.add(new Student("學(xué)生A", "大學(xué)1", 18, 90.0));
?students.add(new Student("學(xué)生A", "大學(xué)1", 18, 76.0));
?students.add(new Student("學(xué)生B", "大學(xué)1", 18, 91.0));
?students.add(new Student("學(xué)生C", "大學(xué)1", 19, 65.0));
?students.add(new Student("學(xué)生D", "大學(xué)2", 20, 80.0));
?students.add(new Student("學(xué)生E", "大學(xué)2", 21, 78.0));
?students.add(new Student("學(xué)生F", "大學(xué)2", 20, 67.0));
?students.add(new Student("學(xué)生G", "大學(xué)3", 22, 87.0));
?students.add(new Student("學(xué)生H", "大學(xué)3", 23, 79.0));
?students.add(new Student("學(xué)生I", "大學(xué)3", 19, 92.0));
?students.add(new Student("學(xué)生J", "大學(xué)4", 20, 84.0));
?List<String> collect = students.stream().filter(student -> student.getAge() > 20).map(student -> student.getName()).limit(3).collect(Collectors.toList());

昨天我沒(méi)有具體說(shuō)明這幾步是如何執(zhí)行的。

畫(huà)張圖來(lái)簡(jiǎn)要的說(shuō)明一下:

  • filter, 根據(jù)條件篩選掉一些元素
  • map,將元素轉(zhuǎn)換成其他的形式
  • limit,將流進(jìn)行截?cái)?,只獲取其中的一部分
  • collect,這里主要就是將流轉(zhuǎn)換成其他的集合對(duì)象,這一步也是流的終端操作,之后也會(huì)聊到。

在這里你可以看到Java 8中的 stream 的設(shè)計(jì),就是只能遍歷一次,并且當(dāng)執(zhí)行完終端操作的時(shí)候,流也是已經(jīng)關(guān)閉或者說(shuō)是消費(fèi)完了。

流操作

上面剛剛提到了終端操作,這也是一個(gè)小小的知識(shí)點(diǎn)。

Stream 的api提供了不少方法,諸如 filter、sotred、limit、map、collect等。

其中 filter、sotred、limit、map 它們的返回結(jié)果仍然是一個(gè)stream 流,這些操作,我們稱之為中間操作。并且它們之間的連接可以形成一個(gè)流水線任務(wù)。

而 collect 則是一個(gè)終端操作,它會(huì)觸發(fā)并執(zhí)行流水線任務(wù),最終關(guān)閉它。

中間操作

就是上面說(shuō)的 filter、map等等,但是需要注意的是,如果流水線上沒(méi)有一個(gè)終端操作,那么你寫(xiě)的filter、map什么的,并不會(huì)執(zhí)行任何處理。

通過(guò)一個(gè)簡(jiǎn)單的案例,來(lái)看一看stream流中的lambda的函數(shù)的執(zhí)行流程。

? ? ?static List<Student> students = new ArrayList<>();
??
? ? ?static {
? ? ? ? ?students.add(new Student("學(xué)生A", "大學(xué)1", 18, 98.0));
? ? ? ? ?students.add(new Student("學(xué)生A", "大學(xué)1", 18, 91.0));
? ? ? ? ?students.add(new Student("學(xué)生A", "大學(xué)1", 18, 90.0));
? ? ? ? ?students.add(new Student("學(xué)生A", "大學(xué)1", 18, 76.0));
? ? ? ? ?students.add(new Student("學(xué)生B", "大學(xué)1", 18, 91.0));
? ? ? ? ?students.add(new Student("學(xué)生C", "大學(xué)1", 19, 65.0));
? ? ? ? ?students.add(new Student("學(xué)生D", "大學(xué)2", 20, 80.0));
? ? ? ? ?students.add(new Student("學(xué)生E", "大學(xué)2", 21, 78.0));
? ? ? ? ?students.add(new Student("學(xué)生F", "大學(xué)2", 20, 67.0));
? ? ? ? ?students.add(new Student("學(xué)生G", "大學(xué)3", 22, 87.0));
? ? ? ? ?students.add(new Student("學(xué)生H", "大學(xué)3", 23, 79.0));
? ? ? ? ?students.add(new Student("學(xué)生I", "大學(xué)3", 19, 92.0));
? ? ? ? ?students.add(new Student("學(xué)生J", "大學(xué)4", 20, 84.0));
? ?  }
?public static void main(String[] args) {
? ? ?List<String> collect = students.stream().filter(student -> {
? ? ? ? ?System.out.println("filter==>" + student.getName() + ":" + student.getAge());
? ? ? ? ?return student.getAge() > 20;
? ?  }).map(student -> {
? ? ? ? ?System.out.println("map==>" + student.getName() + ":" + student.getAge());
? ? ? ? ?return student.getName();
? ?  }).collect(Collectors.toList());
??
?}

輸出:

 filter==>學(xué)生A:18
 map==>學(xué)生A:18
 filter==>學(xué)生A:18
 map==>學(xué)生A:18
 filter==>學(xué)生A:18
 map==>學(xué)生A:18
 filter==>學(xué)生A:18
 map==>學(xué)生A:18
 filter==>學(xué)生B:18
 map==>學(xué)生B:18
 filter==>學(xué)生C:19
 map==>學(xué)生C:19
 filter==>學(xué)生D:20
 filter==>學(xué)生E:21
 filter==>學(xué)生F:20
 filter==>學(xué)生G:22
 filter==>學(xué)生H:23
 filter==>學(xué)生I:19
 map==>學(xué)生I:19
 filter==>學(xué)生J:20

也許到這里還看的不明顯,我們?cè)偌由弦粋€(gè) limit(3),來(lái)看一下這次會(huì)如何輸出

?List<String> collect = students.stream().filter(student -> {
? ? ?System.out.println("filter==>" + student.getName() + ":" + student.getAge());
? ? ?return student.getAge() < 20;
?}).map(student -> {
? ? ?System.out.println("map==>" + student.getName() + ":" + student.getAge());
? ? ?return student.getName();
?}).limit(3).collect(Collectors.toList());
??
?System.out.println(collect);

輸出結(jié)果:

?filter==>學(xué)生A:18
?map==>學(xué)生A:18
?filter==>學(xué)生A:18
?map==>學(xué)生A:18
?filter==>學(xué)生A:18
?map==>學(xué)生A:18
?[學(xué)生A, 學(xué)生A, 學(xué)生A]

1、實(shí)際上這里利用到的 limit(n) 就是俗稱的短路技巧,像我們剛學(xué) &&、| | 語(yǔ)法時(shí)一樣,如果&&條件為false,則會(huì)短路,不執(zhí)行&& 之后的表達(dá)式,這里的 limit 你可以看作是 || 的表達(dá)。

Stream 流在內(nèi)部迭代中主動(dòng)幫我們進(jìn)行了優(yōu)化。

2、另外看似 filter 和 map 是兩個(gè)獨(dú)立的函數(shù),但實(shí)際上他們都是在一次遍歷中所進(jìn)行的。這一點(diǎn)從輸出中也可看出。

終端操作

終端操作,就是觸發(fā)并執(zhí)行流水線任務(wù),最終關(guān)閉流的操作

像之前寫(xiě)的collect(Collectors.toList()) 和 forEach(System.out::println) 都是終端操作。

終端操作其結(jié)果返回的都是流的值,collect返回各種各樣的集合啦,

forEach 返回的就是 void 值。

中間操作:

操 作類型結(jié)果操作參數(shù) 
filter中間StreamPredicateT -> boolean
map中間StreamStream FunctionT -> R
limit中間Stream  
sorted中間StreamComparator(T, T) -> int
distinct中間Stream  

終端操作:

操 作類 型目 的
forEach終端消費(fèi)流中的每個(gè)元素并對(duì)其應(yīng)用 Lambda。這一操作返回 void
count終端返回流中元素的個(gè)數(shù)。這一操作返回 long
collect終端把流歸約成一個(gè)集合,比如 List、Map 甚至是 Integer。

到此這篇關(guān)于Java 8中 Stream小知識(shí)小技巧方法梳理的文章就介紹到這了,更多相關(guān)Java 8 Stream 內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 通過(guò)FeignClient如何獲取文件流steam?is?close問(wèn)題

    通過(guò)FeignClient如何獲取文件流steam?is?close問(wèn)題

    這篇文章主要介紹了通過(guò)FeignClient如何獲取文件流steam?is?close問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-06-06
  • JAVA多線程間通訊常用實(shí)現(xiàn)方法解析

    JAVA多線程間通訊常用實(shí)現(xiàn)方法解析

    這篇文章主要介紹了JAVA多線程間通訊常用實(shí)現(xiàn)方法解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-09-09
  • Java圖片中顯示當(dāng)前時(shí)間的方法

    Java圖片中顯示當(dāng)前時(shí)間的方法

    這篇文章主要介紹了Java圖片中顯示當(dāng)前時(shí)間的方法,需要的朋友可以參考下
    2017-09-09
  • Java多線程中Callable和Future的解讀

    Java多線程中Callable和Future的解讀

    這篇文章主要介紹了Java多線程中Callable和Future的解讀,Callable接口類似于Runnable,從名字就可以看出來(lái)了,但是Runnable不會(huì)返回結(jié)果,并且無(wú)法拋出返回結(jié)果的異常,而Callable功能更強(qiáng)大一些,被線程執(zhí)行后,可以返回值,這個(gè)返回值可以被Future拿到,需要的朋友可以參考下
    2023-09-09
  • Java微信公眾平臺(tái)開(kāi)發(fā)(13) 微信JSSDK中Config配置

    Java微信公眾平臺(tái)開(kāi)發(fā)(13) 微信JSSDK中Config配置

    這篇文章主要為大家詳細(xì)介紹了Java微信公眾平臺(tái)開(kāi)發(fā)第十三步,微信JSSDK中Config配置,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-04-04
  • 關(guān)于java中自定義注解的使用

    關(guān)于java中自定義注解的使用

    這篇文章主要介紹了關(guān)于java中自定義注解的使用,注解像一種修飾符一樣,應(yīng)用于包、類型、構(gòu)造方法、方法、成員變量、參數(shù)及本地變量的聲明語(yǔ)句中,需要的朋友可以參考下
    2023-07-07
  • SpringBoot框架實(shí)現(xiàn)切換啟動(dòng)開(kāi)發(fā)環(huán)境和測(cè)試環(huán)境

    SpringBoot框架實(shí)現(xiàn)切換啟動(dòng)開(kāi)發(fā)環(huán)境和測(cè)試環(huán)境

    這篇文章主要介紹了SpringBoot框架實(shí)現(xiàn)切換啟動(dòng)開(kāi)發(fā)環(huán)境和測(cè)試環(huán)境,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • java實(shí)現(xiàn)俄羅斯方塊游戲

    java實(shí)現(xiàn)俄羅斯方塊游戲

    這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)俄羅斯方塊游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-02-02
  • 微信小程序登錄狀態(tài)java后臺(tái)解密

    微信小程序登錄狀態(tài)java后臺(tái)解密

    這篇文章主要為大家詳細(xì)介紹了微信小程序登錄狀態(tài)java后臺(tái)解密,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-12-12
  • Java利用MD5加鹽實(shí)現(xiàn)對(duì)密碼進(jìn)行加密處理

    Java利用MD5加鹽實(shí)現(xiàn)對(duì)密碼進(jìn)行加密處理

    在開(kāi)發(fā)的時(shí)候,有一些敏感信息是不能直接通過(guò)明白直接保存到數(shù)據(jù)庫(kù)的。最經(jīng)典的就是密碼了。如果直接把密碼以明文的形式入庫(kù),不僅會(huì)泄露用戶的隱私,對(duì)系統(tǒng)也是極其的不厲。本文就來(lái)和大家介紹一下如何對(duì)密碼進(jìn)行加密處理,感興趣的可以了解一下
    2023-02-02

最新評(píng)論