<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>

          Java8新特性-說說Stream的應(yīng)用

          共 6606字,需瀏覽 14分鐘

           ·

          2022-01-01 02:03

          點擊關(guān)注公眾號,Java干貨及時送達


          JDK1.8新特性中較為重要的一塊內(nèi)容就是Stream API了,通過Stream API,我們改變了傳統(tǒng)的集合操作,使得對集合的操作更加簡單和可控。

          初體驗

          在Stream出現(xiàn)以前,我們是如何對集合進行處理的呢?

          比如現(xiàn)在有一個需求,從一個字符串集合中找出長度大于5的字符串,該如何實現(xiàn)呢?代碼如下:

          public?static?void?main(String[]?args)?{
          ????List?list?=?Arrays.asList("apple",?"banana",?"pear",?"orange",?"peach",?"watermelon");
          ????for?(int?i?=?0;?i?????????if?(list.get(i).length()?>?5)?{
          ????????????System.out.println(list.get(i));
          ????????}
          ????}
          }

          這段代碼非常基礎(chǔ),你也可以使用增強for循環(huán)實現(xiàn)這一需求:

          public?static?void?main(String[]?args)?{
          ????List?list?=?Arrays.asList("apple",?"banana",?"pear",?"orange",?"peach",?"watermelon");
          ????for?(String?str?:?list)?{
          ????????if?(str.length()?>?5)?{
          ????????????System.out.println(str);
          ????????}
          ????}
          }

          如果要你將字符串長度大于5的字符串收集起來存入一個新的集合,你就得新建一個集合,然后在循環(huán)里進行添加:

          public?static?void?main(String[]?args)?{
          ????List?list?=?Arrays.asList("apple",?"banana",?"pear",?"orange",?"peach",?"watermelon");
          ????List?newList?=?new?ArrayList<>();
          ????for?(String?str?:?list)?{
          ????????if?(str.length()?>?5)?{
          ????????????newList.add(str);
          ????????}
          ????}
          ????System.out.println(newList);
          }

          上述的這些操作,在Stream API中將會非常容易實現(xiàn),先看一個簡單的例子:

          public?static?void?main(String[]?args)?{
          ????List?list?=?Arrays.asList("apple",?"banana",?"pear",?"orange",?"peach",?"watermelon");
          ????list.forEach(System.out::println);
          }

          遍歷一個集合變得非常簡單,雖然這并不是Steam的API,但這一特性仍然是在JDK1.8之后才支持的,接下來我們就用Steam實現(xiàn)一下將字符串長度大于5的字符串收集成為一個新集合的需求:

          public?static?void?main(String[]?args)?{
          ????List?list?=?Arrays.asList("apple",?"banana",?"pear",?"orange",?"peach",?"watermelon");
          ????List?newList?=?list.stream().map(str?->?{
          ????????if?(str.length()?>?5)?{
          ????????????return?str;
          ????????}
          ????????return?null;
          ????}).collect(Collectors.toList());
          ????System.out.println(newList);
          }

          我們首先不必糾結(jié)為什么這么寫,先來看看它的效果:

          [null,?banana,?null,?orange,?null,?watermelon]

          新集合中雖然都是長度大于5的字符串,但多了一些null值,所以,使用Stream的filter顯然更適合這一需求:

          public?static?void?main(String[]?args)?{
          ????List?list?=?Arrays.asList("apple",?"banana",?"pear",?"orange",?"peach",?"watermelon");
          ????List?newList?=?list.stream().filter(str?->?{
          ????????return?str.length()?>?5;
          ????}).collect(Collectors.toList());
          ????System.out.println(newList);
          }

          運行結(jié)果:

          [banana,?orange,?watermelon]

          熟悉Lambda表達式的同學(xué)肯定能發(fā)現(xiàn),這一寫法還能能進行簡化:

          List?newList?=?list.stream().filter(str?->?str.length()?>?5).collect(Collectors.toList());

          Stream的創(chuàng)建

          見識到了Stream API的廣大神通了吧,接下來我們回到最基本的問題,如何創(chuàng)建一個Stream?

          public?static?void?main(String[]?args)?{
          ????Stream?stream?=?Stream.of(1,?2,?3);
          }

          最簡單的方式便是使用of方法,通過of方法可以創(chuàng)建一個由指定元素組成的Stream,但通常情況下我們并不會使用到該方法,而是使用下面的幾個方法:

          private?static?void?method(List?list,String[]?array)?{
          ????Stream?listStream?=?list.stream();
          ????Stream?arrayStream?=?Arrays.stream(array);
          }

          Stream還支持從指定范圍的數(shù)組中創(chuàng)建一個流(集合不支持):

          private?static?void?method(List?list,String[]?array)?{
          ????Stream?stream?=?Arrays.stream(array,?0,?5);
          }

          創(chuàng)建一個不包含任何元素的流:

          public?static?void?main(String[]?args)?{
          ????Stream?emptyStream?=?Stream.empty();
          }

          使用generate方法創(chuàng)建流:

          public?static?void?main(String[]?args)?{
          ????Stream?stream?=?Stream.generate(Math::random);
          }

          創(chuàng)建流的方式還有很多,這里就不一一列舉了。

          map方法

          在最初的例子中,我們用到了map和filter方法,它們的作用分別是什么以及它們的用法是如何的呢?先來所說map方法,map方法類似于遍歷操作,它會得到Stream中每個元素的映射,并對其一一生效,比如:

          public?static?void?main(String[]?args)?{
          ????Stream?stream?=?Stream.of(1,?2,?3,?4,?5);
          ????List?newList?=?stream.map(num?->?{
          ????????return?num?+?1;
          ????}).collect(Collectors.toList());
          ????System.out.println(newList);
          }

          這段程序的作用就是對流中的每個元素都做加1操作,運行結(jié)果如下:

          [2,?3,?4,?5,?6]

          對于那些需要對集合/流中的每個元素都要做相同操作的需求,就非常適合使用map方法,比如前后端分離開發(fā)中,后端經(jīng)常需要從數(shù)據(jù)庫中查詢出數(shù)據(jù),然后將其封裝成VO傳遞給前端,這一需求就能夠使用map方法實現(xiàn):

          private?static?void?method()?{
          ????List?userList?=?userMapper.findAll();
          ????List?userVOList?=?userList.stream().map(user?->?{
          ????????UserVO?userVO?=?new?UserVO();
          ????????//?拷貝相同的屬性
          ????????BeanUtils.copyProperties(user,?userVO);
          ????????//?處理前端需要的額外屬性
          ????????userVO.setSex(user.getSex?==?1???"男"?:?"女");
          ????????return?userVO;
          ????}).collect(Collectors.toList());
          ????System.out.println(userVOList);
          }

          filter方法

          filter方法與map類似,它也會作用于流中的每個元素,但與其不同的是,filter方法是用來做過濾操作的,在filter中我們需要返回一個boolean類型的值,如果返回為true,則說明該值是我們需要的,如果為false,該值就會被拋棄掉,比如:

          public?static?void?main(String[]?args)?{
          ????Stream?stream?=?Stream.of(1,?35,?7,?4,?3,?5,?54,?57,?36);
          ????List?newList?=?stream.filter(num?->?{
          ????????return?num?>?30;
          ????}).collect(Collectors.toList());
          ????System.out.println(newList);
          }

          這段程序的作用是取出流中數(shù)值大于30的數(shù),運行結(jié)果如下:

          [35,?54,?57,?36]

          filter可以用來對流中的數(shù)據(jù)做過濾處理,比如只想要性別為男的數(shù)據(jù);只想要工資超過2萬的員工信息等等。

          其它操作

          Stream的神奇操作遠不止這些,下面再介紹一些比較常用的功能,比如找出一個集合中的最大值:

          public?static?void?main(String[]?args)?{
          ????List?list?=?Arrays.asList(11,?232,?45,?6346,?14);
          ????int?max?=?0;
          ????for?(Integer?num?:?list)?{
          ????????if(num?>?max){
          ????????????max?=?num;
          ????????}
          ????}
          ????System.out.println(max);
          }

          而如果使用Stream,它將變得非常簡單:

          public?static?void?main(String[]?args)?{
          ????List?list?=?Arrays.asList(11,?232,?45,?6346,?14);
          ????Optional?max?=?list.stream().max(Comparator.naturalOrder());
          ????System.out.println(max.get());
          }

          求最小值,只需使用min方法即可:

          public?static?void?main(String[]?args)?{
          ????List?list?=?Arrays.asList(11,?232,?45,?6346,?14);
          ????Optional?max?=?list.stream().min(Comparator.naturalOrder());
          ????System.out.println(max.get());
          }

          求和:

          public?static?void?main(String[]?args)?{
          ????List?list?=?Arrays.asList(11,?232,?45,?6346,?14);
          ????Optional?sum?=?list.stream().reduce(Integer::sum);
          ????System.out.println(sum.get());
          }

          注意事項

          在使用Strema API時需要注意的地方就是Lambda表達式的編寫,如:

          List?list?=?wordList.stream().filter(word?->?{
          ????return?word.startsWith("p");
          list.forEach(System.out::println);

          對于這樣的一段程序,因為Lambda表達式體中僅包含了一條返回語句,所以表達式可以簡寫:

          List?list?=?wordList.stream().
          ????filter(word?->?word.startsWith("p")).collect(Collectors.toList());
          list.forEach(System.out::println);

          又比如:

          List?numList?=?Arrays.asList(1,?2,?3,?4,?5,?6,?7,?8,?9,?10);
          Optional?sum?=?numList.stream().reduce((x,?y)?->?{
          ????return?x?+?y;
          });
          System.out.println(sum);

          首先因為Lambda表達式體僅包含一條返回語句,所以可以簡寫:

          Optional?sum?=?numList.stream().reduce((x,?y)?->?x?+?y);

          我們也可以調(diào)用Integer類的靜態(tài)方法sum進行求和:

          Optional?sum?=?numList.stream().reduce((x,?y)?->?Integer.sum(x,?y));

          又因為Lambda表達式體中僅包含一條語句,且該語句調(diào)用了一個絕對存在的方法,則可以簡寫為:

          Optional?sum?=?numList.stream().reduce(Integer::sum);

          這就是Lambda表達式中的方法引用,具體細節(jié)可以去了解一下Lambda的相關(guān)內(nèi)容。

          最后就是Stream的一些其他類型,當(dāng)你使用of方法創(chuàng)建一個流時:

          Stream?stream?=?Stream.of(1,?2,?3,?4,?5,?6,?7,?8,?9,?10);

          調(diào)用Stream類的of方法傳入的是基本類型數(shù)據(jù),但是會得到一個包裝類型的Stream,我們知道,基本類型需要裝箱成為包裝類型,這一操作在數(shù)據(jù)量龐大的情況下是比較低效的,Stream API也考慮到這一點,所以提供了對應(yīng)包裝類型的Strema,如下:

          IntStream?intStream?=?IntStream.of(1,?2,?'a',?'z');
          LongStream?longStream?=?LongStream.of(10L);
          DoubleStream?doubleStream?=?DoubleStream.of(1.1f,?2.2);


          1、Log4j2維護者吐槽沒工資還要挨罵,GO安全負責(zé)人建議開源作者向公司收費

          2、太難了!讓程序員崩潰的8個瞬間

          3、2021年程序員們都在用的神級數(shù)據(jù)庫

          4、Windows重要功能被閹割,全球用戶怒噴數(shù)月后微軟終于悔改

          5、牛逼!國產(chǎn)開源的遠程桌面火了,只有9MB 支持自建中繼器!

          6、摔到老三的 Java,未來在哪?

          7、真香!用 IDEA 神器看源碼,效率真高!

          點分享

          點收藏

          點點贊

          點在看

          瀏覽 42
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <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>
                    久久岛国电影免费观看软件 | 美国人A一级毛片 | 欧美成人免费精品 | 青青草手机视频在线 | 77毛片|