最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java?8中?Stream小知識小技巧方法梳理

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

前言

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

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

分成三部分:

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

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

只能遍歷的一次 Stream

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

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

?/**
? ? ? * 圖個樂子
? ? ? */
?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);
?}

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

?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)被操作完或者關閉啦~

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

我的回答肯定是 Java 中的設計是如此。

我們先來回憶一下我昨天沒提到的一個知識點:

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

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

昨天我沒有具體說明這幾步是如何執(zhí)行的

畫張圖來簡要的說明一下:

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

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

流操作

上面剛剛提到了終端操作,這也是一個小小的知識點。

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

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

而 collect 則是一個終端操作,它會觸發(fā)并執(zhí)行流水線任務,最終關閉它

中間操作

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

通過一個簡單的案例,來看一看stream流中的lambda的函數(shù)的執(zhí)行流程。

? ? ?static List<Student> students = new ArrayList<>();
??
? ? ?static {
? ? ? ? ?students.add(new Student("學生A", "大學1", 18, 98.0));
? ? ? ? ?students.add(new Student("學生A", "大學1", 18, 91.0));
? ? ? ? ?students.add(new Student("學生A", "大學1", 18, 90.0));
? ? ? ? ?students.add(new Student("學生A", "大學1", 18, 76.0));
? ? ? ? ?students.add(new Student("學生B", "大學1", 18, 91.0));
? ? ? ? ?students.add(new Student("學生C", "大學1", 19, 65.0));
? ? ? ? ?students.add(new Student("學生D", "大學2", 20, 80.0));
? ? ? ? ?students.add(new Student("學生E", "大學2", 21, 78.0));
? ? ? ? ?students.add(new Student("學生F", "大學2", 20, 67.0));
? ? ? ? ?students.add(new Student("學生G", "大學3", 22, 87.0));
? ? ? ? ?students.add(new Student("學生H", "大學3", 23, 79.0));
? ? ? ? ?students.add(new Student("學生I", "大學3", 19, 92.0));
? ? ? ? ?students.add(new Student("學生J", "大學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==>學生A:18
 map==>學生A:18
 filter==>學生A:18
 map==>學生A:18
 filter==>學生A:18
 map==>學生A:18
 filter==>學生A:18
 map==>學生A:18
 filter==>學生B:18
 map==>學生B:18
 filter==>學生C:19
 map==>學生C:19
 filter==>學生D:20
 filter==>學生E:21
 filter==>學生F:20
 filter==>學生G:22
 filter==>學生H:23
 filter==>學生I:19
 map==>學生I:19
 filter==>學生J:20

也許到這里還看的不明顯,我們再加上一個 limit(3),來看一下這次會如何輸出

?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);

輸出結果:

?filter==>學生A:18
?map==>學生A:18
?filter==>學生A:18
?map==>學生A:18
?filter==>學生A:18
?map==>學生A:18
?[學生A, 學生A, 學生A]

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

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

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

終端操作

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

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

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

forEach 返回的就是 void 值。

中間操作:

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

終端操作:

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

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

相關文章

  • Java自定義協(xié)議報文封裝 添加Crc32校驗的實例

    Java自定義協(xié)議報文封裝 添加Crc32校驗的實例

    下面小編就為大家分享一篇Java自定義協(xié)議報文封裝 添加Crc32校驗的實例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-01-01
  • Java?詳解分析鏈表的中間節(jié)點

    Java?詳解分析鏈表的中間節(jié)點

    鏈表是基本的數(shù)據(jù)結構之一,面試題中鏈表占很大一部分,可見鏈表操作是非常重要的。本篇文章我們來探究一下如何獲取鏈表的中間節(jié)點
    2022-01-01
  • Java四種常用線程池的詳細介紹

    Java四種常用線程池的詳細介紹

    今天小編就為大家分享一篇關于Java四種常用線程池的詳細介紹,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-03-03
  • Java多線程面試題(面試官常問)

    Java多線程面試題(面試官常問)

    這篇文章主要介紹了Java多線程面試題(面試官常問),本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-03-03
  • JAVA基礎之注解與反射的使用方法和場景

    JAVA基礎之注解與反射的使用方法和場景

    這篇文章主要給大家介紹了關于JAVA基礎之注解與反射的使用方法和場景的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-03-03
  • SpringBoot+mybatis實現(xiàn)多數(shù)據(jù)源支持操作

    SpringBoot+mybatis實現(xiàn)多數(shù)據(jù)源支持操作

    這篇文章主要介紹了SpringBoot+mybatis實現(xiàn)多數(shù)據(jù)源支持操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-10-10
  • gRPC與SpringBoot整合思路和步驟

    gRPC與SpringBoot整合思路和步驟

    在現(xiàn)代微服務架構中,gRPC已經(jīng)成為了非常受歡迎的通信協(xié)議,與SpringBoot整合,它為開發(fā)者提供了簡潔、高效構建分布式應用,在整合gRPC與SpringBoot時,將gRPC的服務端和客戶端分別封裝到SpringBoot的應用中,感興趣的朋友一起看看吧
    2023-08-08
  • Java語言中的文件數(shù)據(jù)流示例詳解

    Java語言中的文件數(shù)據(jù)流示例詳解

    這篇文章主要為大家介紹了Java語言中的文件數(shù)據(jù)流示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-11-11
  • Java  隊列實現(xiàn)原理及簡單實現(xiàn)代碼

    Java 隊列實現(xiàn)原理及簡單實現(xiàn)代碼

    這篇文章主要介紹了Java 隊列實現(xiàn)原理及簡單實現(xiàn)代碼的相關資料,需要的朋友可以參考下
    2016-10-10
  • spring boot加載freemarker模板路徑的方法

    spring boot加載freemarker模板路徑的方法

    這篇文章主要介紹了spring boot加載freemarker模板路徑的方法,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-11-11

最新評論

新野县| 雅江县| 育儿| 乐山市| 民权县| 阜新| 兖州市| 运城市| 运城市| 兴义市| 谷城县| 谷城县| 二连浩特市| 蒙山县| 佛教| 晴隆县| 和田县| 关岭| 东安县| 呼和浩特市| 延边| 历史| 杭州市| 天等县| 石台县| 东方市| 南雄市| 皮山县| 手游| 隆尧县| 大足县| 兴化市| 定南县| 阳朔县| 裕民县| 晋中市| 延吉市| 商都县| 通辽市| 苍梧县| 深泽县|