<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          玩轉(zhuǎn) Java8 Stream,常用方法大合集

          共 9458字,需瀏覽 19分鐘

           ·

          2022-04-10 06:29


          來(lái)源:blog.csdn.net/y_k_y/article/details/84633001

          一、概述

          Stream 是 Java8 中處理集合的關(guān)鍵抽象概念,它可以指定你希望對(duì)集合進(jìn)行的操作,可以執(zhí)行非常復(fù)雜的查找、過(guò)濾和映射數(shù)據(jù)等操作。使用Stream API 對(duì)集合數(shù)據(jù)進(jìn)行操作,就類似于使用 SQL 執(zhí)行的數(shù)據(jù)庫(kù)查詢。也可以使用 Stream API 來(lái)并行執(zhí)行操作。

          簡(jiǎn)而言之,Stream API 提供了一種高效且易于使用的處理數(shù)據(jù)的方式。

          特點(diǎn):

          1. 不是數(shù)據(jù)結(jié)構(gòu),不會(huì)保存數(shù)據(jù)。

          2. 不會(huì)修改原來(lái)的數(shù)據(jù)源,它會(huì)將操作后的數(shù)據(jù)保存到另外一個(gè)對(duì)象中。(保留意見(jiàn):畢竟peek方法可以修改流中元素)

          3. 惰性求值,流在中間處理過(guò)程中,只是對(duì)操作進(jìn)行了記錄,并不會(huì)立即執(zhí)行,需要等到執(zhí)行終止操作的時(shí)候才會(huì)進(jìn)行實(shí)際的計(jì)算。

          二、分類

          • 無(wú)狀態(tài): 指元素的處理不受之前元素的影響;

          • 有狀態(tài): 指該操作只有拿到所有元素之后才能繼續(xù)下去。

          • 非短路操作: 指必須處理所有元素才能得到最終結(jié)果;

          • 短路操作: 指遇到某些符合條件的元素就可以得到最終結(jié)果,如 A || B,只要A為true,則無(wú)需判斷B的結(jié)果。

          三、具體用法

          1. 流的常用創(chuàng)建方法

          1.1 使用Collection下的 stream() parallelStream() 方法

          List?list?=?new?ArrayList<>();
          Stream?stream?=?list.stream();?//獲取一個(gè)順序流
          Stream?parallelStream?=?list.parallelStream();?//獲取一個(gè)并行流

          1.2 使用Arrays 中的stream()方法,將數(shù)組轉(zhuǎn)成流

          Integer[]?nums?=?new?Integer[10];
          Stream?stream?=?Arrays.stream(nums);

          1.3 使用Stream中的靜態(tài)方法:of()iterate()generate()

          Stream?stream?=?Stream.of(1,2,3,4,5,6);
          ?
          Stream?stream2?=?Stream.iterate(0,?(x)?->?x?+?2).limit(6);
          stream2.forEach(System.out::println);?//?0?2?4?6?8?10
          ?
          Stream?stream3?=?Stream.generate(Math::random).limit(2);
          stream3.forEach(System.out::println);

          1.4 使用 BufferedReader.lines() 方法,將每行內(nèi)容轉(zhuǎn)成流

          BufferedReader?reader?=?new?BufferedReader(new?FileReader("F:\\test_stream.txt"));
          Stream?lineStream?=?reader.lines();
          lineStream.forEach(System.out::println);

          1.5 使用 Pattern.splitAsStream() 方法,將字符串分隔成流

          Pattern?pattern?=?Pattern.compile(",");
          Stream?stringStream?=?pattern.splitAsStream("a,b,c,d");
          stringStream.forEach(System.out::println);

          2. 流的中間操作

          2.1 篩選與切片

          • filter:過(guò)濾流中的某些元素
          • limit(n):獲取n個(gè)元素
          • skip(n):跳過(guò)n元素,配合limit(n)可實(shí)現(xiàn)分頁(yè)
          • distinct:通過(guò)流中元素的 hashCode()equals() 去除重復(fù)元素
          Stream?stream?=?Stream.of(6,?4,?6,?7,?3,?9,?8,?10,?12,?14,?14);
          ?
          Stream?newStream?=?stream.filter(s?->?s?>?5)?//6?6?7?9?8?10?12?14?14
          ????????.distinct()?//6?7?9?8?10?12?14
          ????????.skip(2)?//9?8?10?12?14
          ????????.limit(2);?//9?8
          newStream.forEach(System.out::println);

          2.2 映射

          • map: 接收一個(gè)函數(shù)作為參數(shù),該函數(shù)會(huì)被應(yīng)用到每個(gè)元素上,并將其映射成一個(gè)新的元素。
          • flatMap: 接收一個(gè)函數(shù)作為參數(shù),將流中的每個(gè)值都換成另一個(gè)流,然后把所有流連接成一個(gè)流。
          List?list?=?Arrays.asList("a,b,c",?"1,2,3");
          ?
          //將每個(gè)元素轉(zhuǎn)成一個(gè)新的且不帶逗號(hào)的元素
          Stream?s1?=?list.stream().map(s?->?s.replaceAll(",",?""));
          s1.forEach(System.out::println);?//?abc??123
          ?
          Stream?s3?=?list.stream().flatMap(s?->?{
          ????//將每個(gè)元素轉(zhuǎn)換成一個(gè)stream
          ????String[]?split?=?s.split(",");
          ????Stream?s2?=?Arrays.stream(split);
          ????return?s2;
          });
          s3.forEach(System.out::println);?//?a?b?c?1?2?3

          2.3 排序

          • sorted():自然排序,流中元素需實(shí)現(xiàn)Comparable接口
          • sorted(Comparator com):定制排序,自定義Comparator排序器
          List?list?=?Arrays.asList("aa",?"ff",?"dd");
          //String?類自身已實(shí)現(xiàn)Compareable接口
          list.stream().sorted().forEach(System.out::println);//?aa?dd?ff
          ?
          Student?s1?=?new?Student("aa",?10);
          Student?s2?=?new?Student("bb",?20);
          Student?s3?=?new?Student("aa",?30);
          Student?s4?=?new?Student("dd",?40);
          List?studentList?=?Arrays.asList(s1,?s2,?s3,?s4);
          ?
          //自定義排序:先按姓名升序,姓名相同則按年齡升序
          studentList.stream().sorted(
          ????????(o1,?o2)?->?{
          ????????????if?(o1.getName().equals(o2.getName()))?{
          ????????????????return?o1.getAge()?-?o2.getAge();
          ????????????}?else?{
          ????????????????return?o1.getName().compareTo(o2.getName());
          ????????????}
          ????????}
          ).forEach(System.out::println);

          2.4 消費(fèi)

          • peek:如同于map,能得到流中的每一個(gè)元素。但map接收的是一個(gè)Function表達(dá)式,有返回值;而peek接收的是Consumer表達(dá)式,沒(méi)有返回值。
          Student?s1?=?new?Student("aa",?10);
          Student?s2?=?new?Student("bb",?20);
          List?studentList?=?Arrays.asList(s1,?s2);
          ?
          studentList.stream()
          ????????.peek(o?->?o.setAge(100))
          ????????.forEach(System.out::println);???
          ?
          //結(jié)果:
          Student{name='aa',?age=100}
          Student{name='bb',?age=100}????????????

          3. 流的終止操作

          3.1 匹配、聚合操作

          • allMatch:接收一個(gè) Predicate 函數(shù),當(dāng)流中每個(gè)元素都符合該斷言時(shí)才返回true,否則返回false
          • noneMatch:接收一個(gè) Predicate 函數(shù),當(dāng)流中每個(gè)元素都不符合該斷言時(shí)才返回true,否則返回false
          • anyMatch:接收一個(gè) Predicate 函數(shù),只要流中有一個(gè)元素滿足該斷言則返回true,否則返回false
          • findFirst:返回流中第一個(gè)元素
          • findAny:返回流中的任意元素
          • count:返回流中元素的總個(gè)數(shù)
          • max:返回流中元素最大值
          • min:返回流中元素最小值??Java項(xiàng)目分享
          List?list?=?Arrays.asList(1,?2,?3,?4,?5);
          ?
          boolean?allMatch?=?list.stream().allMatch(e?->?e?>?10);?//false
          boolean?noneMatch?=?list.stream().noneMatch(e?->?e?>?10);?//true
          boolean?anyMatch?=?list.stream().anyMatch(e?->?e?>?4);??//true
          ?
          Integer?findFirst?=?list.stream().findFirst().get();?//1
          Integer?findAny?=?list.stream().findAny().get();?//1
          ?
          long?count?=?list.stream().count();?//5
          Integer?max?=?list.stream().max(Integer::compareTo).get();?//5
          Integer?min?=?list.stream().min(Integer::compareTo).get();?//1

          3.2 規(guī)約操作

          • Optional reduce(BinaryOperator accumulator):第一次執(zhí)行時(shí),accumulator函數(shù)的第一個(gè)參數(shù)為流中的第一個(gè)元素,第二個(gè)參數(shù)為流中元素的第二個(gè)元素;第二次執(zhí)行時(shí),第一個(gè)參數(shù)為第一次函數(shù)執(zhí)行的結(jié)果,第二個(gè)參數(shù)為流中的第三個(gè)元素;依次類推。

          • T reduce(T identity, BinaryOperator accumulator):流程跟上面一樣,只是第一次執(zhí)行時(shí),accumulator函數(shù)的第一個(gè)參數(shù)為identity,而第二個(gè)參數(shù)為流中的第一個(gè)元素。

          • U reduce(U identity,BiFunction accumulator,BinaryOperator combiner):在串行流(stream)中,該方法跟第二個(gè)方法一樣,即第三個(gè)參數(shù)combiner不會(huì)起作用。在并行流(parallelStream)中,我們知道流被fork join出多個(gè)線程進(jìn)行執(zhí)行,此時(shí)每個(gè)線程的執(zhí)行流程就跟第二個(gè)方法reduce(identity,accumulator)一樣,而第三個(gè)參數(shù)combiner函數(shù),則是將每個(gè)線程的執(zhí)行結(jié)果當(dāng)成一個(gè)新的流,然后使用第一個(gè)方法reduce(accumulator)流程進(jìn)行規(guī)約。?Java項(xiàng)目分享

          //經(jīng)過(guò)測(cè)試,當(dāng)元素個(gè)數(shù)小于24時(shí),并行時(shí)線程數(shù)等于元素個(gè)數(shù),當(dāng)大于等于24時(shí),并行時(shí)線程數(shù)為16
          List?list?=?Arrays.asList(1,?2,?3,?4,?5,?6,?7,?8,?9,?10,?11,?12,?13,?14,?15,?16,?17,?18,?19,?20,?21,?22,?23,?24);
          ?
          Integer?v?=?list.stream().reduce((x1,?x2)?->?x1?+?x2).get();
          System.out.println(v);???//?300
          ?
          Integer?v1?=?list.stream().reduce(10,?(x1,?x2)?->?x1?+?x2);
          System.out.println(v1);??//310
          ?
          Integer?v2?=?list.stream().reduce(0,
          ????????(x1,?x2)?->?{
          ????????????System.out.println("stream?accumulator:?x1:"?+?x1?+?"??x2:"?+?x2);
          ????????????return?x1?-?x2;
          ????????},
          ????????(x1,?x2)?->?{
          ????????????System.out.println("stream?combiner:?x1:"?+?x1?+?"??x2:"?+?x2);
          ????????????return?x1?*?x2;
          ????????});
          System.out.println(v2);?//?-300
          ?
          Integer?v3?=?list.parallelStream().reduce(0,
          ????????(x1,?x2)?->?{
          ????????????System.out.println("parallelStream?accumulator:?x1:"?+?x1?+?"??x2:"?+?x2);
          ????????????return?x1?-?x2;
          ????????},
          ????????(x1,?x2)?->?{
          ????????????System.out.println("parallelStream?combiner:?x1:"?+?x1?+?"??x2:"?+?x2);
          ????????????return?x1?*?x2;
          ????????});
          System.out.println(v3);?//197474048

          3.3 收集操作

          collect:接收一個(gè)Collector實(shí)例,將流中元素收集成另外一個(gè)數(shù)據(jù)結(jié)構(gòu)。

          Collector 是一個(gè)接口,有以下5個(gè)抽象方法:

          3.3.1 Collector 工具庫(kù):Collectors

          Student?s1?=?new?Student("aa",?10,1);
          Student?s2?=?new?Student("bb",?20,2);
          Student?s3?=?new?Student("cc",?10,3);
          List?list?=?Arrays.asList(s1,?s2,?s3);
          ?
          //裝成list
          List?ageList?=?list.stream().map(Student::getAge).collect(Collectors.toList());?//?[10,?20,?10]
          ?
          //轉(zhuǎn)成set
          Set?ageSet?=?list.stream().map(Student::getAge).collect(Collectors.toSet());?//?[20,?10]
          ?
          //轉(zhuǎn)成map,注:key不能相同,否則報(bào)錯(cuò)
          Map?studentMap?=?list.stream().collect(Collectors.toMap(Student::getName,?Student::getAge));?//?{cc=10,?bb=20,?aa=10}
          ?
          //字符串分隔符連接
          String?joinName?=?list.stream().map(Student::getName).collect(Collectors.joining(",",?"(",?")"));?//?(aa,bb,cc)
          ?
          //聚合操作
          //1.學(xué)生總數(shù)
          Long?count?=?list.stream().collect(Collectors.counting());?//?3
          //2.最大年齡?(最小的minBy同理)
          Integer?maxAge?=?list.stream().map(Student::getAge).collect(Collectors.maxBy(Integer::compare)).get();?//?20
          //3.所有人的年齡
          Integer?sumAge?=?list.stream().collect(Collectors.summingInt(Student::getAge));?//?40
          //4.平均年齡
          Double?averageAge?=?list.stream().collect(Collectors.averagingDouble(Student::getAge));?//?13.333333333333334
          //?帶上以上所有方法
          DoubleSummaryStatistics?statistics?=?list.stream().collect(Collectors.summarizingDouble(Student::getAge));
          System.out.println("count:"?+?statistics.getCount()?+?",max:"?+?statistics.getMax()?+?",sum:"?+?statistics.getSum()?+?",average:"?+?statistics.getAverage());
          ?
          //分組
          Map>?ageMap?=?list.stream().collect(Collectors.groupingBy(Student::getAge));
          //多重分組,先根據(jù)類型分再根據(jù)年齡分
          Map>>?typeAgeMap?=?list.stream().collect(Collectors.groupingBy(Student::getType,?Collectors.groupingBy(Student::getAge)));
          ?
          //分區(qū)
          //分成兩部分,一部分大于10歲,一部分小于等于10歲
          Map>?partMap?=?list.stream().collect(Collectors.partitioningBy(v?->?v.getAge()?>?10));
          ?
          //規(guī)約
          Integer?allAge?=?list.stream().map(Student::getAge).collect(Collectors.reducing(Integer::sum)).get();?//40

          3.3.2 Collectors.toList() 解析

          //toList?源碼
          public?static??Collector>?toList()?{
          ????return?new?CollectorImpl<>((Supplier>)?ArrayList::new,?List::add,
          ????????????(left,?right)?->?{
          ????????????????left.addAll(right);
          ????????????????return?left;
          ????????????},?CH_ID);
          }
          ?
          //為了更好地理解,我們轉(zhuǎn)化一下源碼中的lambda表達(dá)式
          public??Collector>?toList()?{
          ????Supplier>?supplier?=?()?->?new?ArrayList();
          ????BiConsumer,?T>?accumulator?=?(list,?t)?->?list.add(t);
          ????BinaryOperator>?combiner?=?(list1,?list2)?->?{
          ????????list1.addAll(list2);
          ????????return?list1;
          ????};
          ????Function,?List>?finisher?=?(list)?->?list;
          ????Set?characteristics?=?Collections.unmodifiableSet(EnumSet.of(Collector.Characteristics.IDENTITY_FINISH));
          ?
          ????return?new?Collector,?List>()?{
          ????????@Override
          ????????public?Supplier?supplier()?{
          ????????????return?supplier;
          ????????}
          ?
          ????????@Override
          ????????public?BiConsumer?accumulator()?{
          ????????????return?accumulator;
          ????????}
          ?
          ????????@Override
          ????????public?BinaryOperator?combiner()?{
          ????????????return?combiner;
          ????????}
          ?
          ????????@Override
          ????????public?Function?finisher()?{
          ????????????return?finisher;
          ????????}
          ?
          ????????@Override
          ????????public?Set?characteristics()?{
          ????????????return?characteristics;
          ????????}
          ????};
          ?
          }

          程序汪資料鏈接

          程序汪接的7個(gè)私活都在這里,經(jīng)驗(yàn)整理

          Java項(xiàng)目分享 最新整理全集,找項(xiàng)目不累啦 06版

          堪稱神級(jí)的Spring Boot手冊(cè),從基礎(chǔ)入門到實(shí)戰(zhàn)進(jìn)階

          臥槽!字節(jié)跳動(dòng)《算法中文手冊(cè)》火了,完整版 PDF 開(kāi)放下載!

          臥槽!阿里大佬總結(jié)的《圖解Java》火了,完整版PDF開(kāi)放下載!

          字節(jié)跳動(dòng)總結(jié)的設(shè)計(jì)模式 PDF 火了,完整版開(kāi)放下載!


          歡迎添加程序汪個(gè)人微信 itwang009? 進(jìn)粉絲群或圍觀朋友圈

          瀏覽 25
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                    <th id="afajh"><progress id="afajh"></progress></th>
                    7799天天综合网 | 人人澡人人人妻人人奭 | 小黄片免费观看 | 操婷婷五月天 | 欧美性受XXXX黑人XYX性爽公 |