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

          相信我,使用 Stream 真的可以讓代碼更優(yōu)雅!

          共 1464字,需瀏覽 3分鐘

           ·

          2022-05-26 20:14


          前言

          雖然 stream在 Java8 中就已經(jīng)被引入,但是大多數(shù)人卻沒有去使用這個(gè)十分有用的特性,本文就通過介紹幾個(gè)通過使用stream讓代碼更簡(jiǎn)潔、可讀,來讓你了解stream的方便之處。

          技巧

          數(shù)組轉(zhuǎn)集合

          相信經(jīng)常刷LeetCode的小伙伴,偶爾會(huì)遇到需要將List與基本類型數(shù)組進(jìn)行互轉(zhuǎn)的情況,然后就需要寫像下面這樣的代碼:

          //?將?List?元素存儲(chǔ)到數(shù)組中
          List?list?=?new?ArrayList<>(Arrays.asList(1,?2,?3,?4,?5));
          int[]?arr?=?new?int[list.size()];
          Integer[]?temp?=?list.toArray(new?Integer[0]);
          for?(int?i?=?0;?i??arr[i]?=?temp[i];
          }

          //?將數(shù)組元素?存儲(chǔ)到?List?中
          int[]?arr?=?{1,?2,?3,?4,?5};
          List?list?=?new?ArrayList<>();
          for?(int?val?:?arr)?{
          ?list.add(val);
          }

          以上兩個(gè)轉(zhuǎn)換雖然寫著還不算麻煩,但是每次都需要寫一個(gè)循環(huán),尤其在數(shù)組轉(zhuǎn)List的時(shí)候還需要使用一個(gè)臨時(shí)數(shù)組,都會(huì)讓人看著很不舒服,但是如果使用了stream就會(huì)大不一樣,用stream實(shí)現(xiàn)了相同功能的代碼如下:

          //?將?List?元素存儲(chǔ)到數(shù)組中
          List?list?=?new?ArrayList<>(Arrays.asList(1,?2,?3,?4,?5));
          int[]?arr?=?list.stream().mapToInt(Integer::intValue).toArray();

          //?將數(shù)組元素?存儲(chǔ)到?List?中
          int[]?arr?=?{1,?2,?3,?4,?5};
          List?list?=?IntStream.of(arr).boxed().collect(Collectors.toList());

          可以發(fā)現(xiàn)通過使用stream,我們能夠在寫代碼的時(shí)候更加連貫,代碼也更加可靠易維護(hù),注意力也可以放在業(yè)務(wù)功能上,相信各位就算對(duì)lambda語法并不是太熟悉,在閱讀上面代碼的時(shí)候,也很容易能夠看懂。

          統(tǒng)計(jì)數(shù)組元素中的個(gè)數(shù)

          假設(shè)我們現(xiàn)在需要統(tǒng)計(jì)并輸出一個(gè)有重復(fù)元素的數(shù)組中每個(gè)元素及對(duì)應(yīng)元素出現(xiàn)的個(gè)數(shù),相信各位都能夠想到,我們使用一個(gè)Map就很容易解決這個(gè)問題,代碼如下:

          String[]?arr?=?{"a",?"c",?"a",?"b",?"d",?"c"};
          Map?map?=?new?HashMap<>();
          for?(String?s?:?arr)?{
          ????if?(map.containsKey(s))?{
          ????????map.put(s,?map.get(s)?+?1);
          ????}?else?{
          ????????map.put(s,?1);
          ????}
          }
          map.forEach((key,?value)?->?System.out.println(key?+?"?:?"?+?value));

          如果對(duì)Map中的API更加熟悉的小伙伴,可能會(huì)寫出下面這個(gè)更加簡(jiǎn)潔的代碼:

          String[]?arr?=?{"a",?"c",?"a",?"b",?"d",?"c"};
          Map?map?=?new?HashMap<>();
          for?(String?s?:?arr)?{
          ????map.put(s,?map.getOrDefault(s,?0)?+?1);
          }
          map.forEach((key,?value)?->?System.out.println(key?+?"?:?"?+?value));

          但是,如果使用stream,我們還能寫出更加簡(jiǎn)潔的代碼,同樣不需要寫煩人的循環(huán)了,而且只需兩行代碼即可(為了提高可讀性,進(jìn)行了換行):

          String[]?arr?=?{"a",?"c",?"a",?"b",?"d",?"c"};
          Stream.of(arr)
          ??????.collect(Collectors.toMap(k?->?k,?k?->?1,?Integer::sum))
          ??????.forEach((k,?v)?->?System.out.println(k?+?"?:?"?+?v));
          注意

          在上面的代碼中,Collectors.toMap(k -> k, k -> 1, Integer::sum)這一部分可能不好理解,對(duì)于這里面的三個(gè)參數(shù),第一個(gè)參數(shù)代表將arr中的每一個(gè)元素作為Map中的key,第二個(gè)參數(shù)代表每一個(gè)key所對(duì)應(yīng)的value,在這里每一個(gè)元素都對(duì)應(yīng)個(gè)數(shù)1,第三個(gè)參數(shù)代表,如果存在相同的key,該如何進(jìn)行合并,這里通過使用Integer::sum,代表將具有相同key的元素進(jìn)行合并時(shí),其value進(jìn)行相加,這樣便實(shí)現(xiàn)了每個(gè)元素個(gè)數(shù)的統(tǒng)計(jì)。?Java項(xiàng)目分享 ?最新整理全集

          基本數(shù)據(jù)類型的數(shù)組自定義排序

          有時(shí)我們會(huì)遇到對(duì)基本數(shù)據(jù)類型的數(shù)組進(jìn)行自定義排序的情況,不同于包裝類型的數(shù)組和集合可以直接使用比較器,我們只能通過將基本數(shù)組類型的數(shù)組轉(zhuǎn)為包裝類型或者存儲(chǔ)在集合中,在排序完成后再轉(zhuǎn)為基本類型的數(shù)組,再者,我們只能通過手寫排序算法,修改排序算法中的比較進(jìn)行實(shí)現(xiàn)。

          不管是哪種方法,我們都沒辦法將精力放在邏輯功能上,必須寫一些額外的代碼,甚至是修改底層邏輯,就像下面的代碼一樣(實(shí)現(xiàn)數(shù)組逆序):

          int[]?arr?=?{1,?5,?9,?7,?2,?3,?7,?-1,?0,?3};
          //?將數(shù)組轉(zhuǎn)為包裝類型再進(jìn)行自定義排序
          Integer[]?temp?=?new?Integer[arr.length];
          for?(int?i?=?0;?i?????temp[i]?=?arr[i];
          }
          Arrays.sort(temp,?Comparator.reverseOrder());
          for?(int?i?=?0;?i?????arr[i]?=?temp[i];
          }

          //?將數(shù)組轉(zhuǎn)為集合類型再進(jìn)行自定義排序
          List?list?=?new?ArrayList<>();
          for?(int?val?:?arr)?{
          ????list.add(val);
          }
          list.sort(Collections.reverseOrder());
          for?(int?i?=?0;?i?????arr[i]?=?list.get(i);
          }

          //?通過手寫排序算法修改比較規(guī)則實(shí)現(xiàn)
          //?為了讓代碼更加簡(jiǎn)潔,使用了最暴力且沒有優(yōu)化的冒泡排序
          int[]?arr?=?{1,?5,?9,?7,?2,?3,?7,?-1,?0,?3};
          for?(int?i?=?0;?i?????for?(int?j?=?0;?j?1;?j++)?{
          ????????if?(arr[j]?1])?{
          ????????????int?temp?=?arr[j];
          ????????????arr[j]?=?arr[j?+?1];
          ????????????arr[j?+?1]?=?temp;
          ????????}
          ????}
          }

          可以發(fā)現(xiàn)以上幾種方法,我們都需要寫很多代碼,無法將注意力集中在設(shè)計(jì)自定義排序這個(gè)問題上,但是通過使用stream,我們就可以寫出下面這樣簡(jiǎn)潔的代碼(如果愿意的話,你也可以把一系列的鏈?zhǔn)讲僮鲗懺谝恍猩?,但為了代碼的可讀性,不建議那么做):?Java項(xiàng)目分享 ?最新整理全集

          int[]?arr?=?{1,?5,?9,?7,?2,?3,?7,?-1,?0,?3};
          arr?=?IntStream.of(arr)
          ???????????????.boxed()
          ???????????????.sorted(Comparator.reverseOrder())
          ???????????????.mapToInt(Integer::intValue)
          ???????????????.toArray();
          注意

          在這里其實(shí)為了實(shí)現(xiàn)數(shù)組的逆序,我們只需要調(diào)用Arrays的sort方法,然后再進(jìn)行數(shù)組元素的反轉(zhuǎn)即可,不過因?yàn)槭菫榱酥v解自定義排序,大多數(shù)情況下不會(huì)是數(shù)組逆序這么簡(jiǎn)單,所以我就寫了更加通用一些的代碼。

          統(tǒng)計(jì)數(shù)組中前 k 個(gè)個(gè)高頻元素

          在最后,我們通過一道題來進(jìn)行實(shí)戰(zhàn)以便更好的體驗(yàn)stream的強(qiáng)大之處,當(dāng)然我們?cè)诰毩?xí)該題的時(shí)候,更需要從算法的角度去考慮該題的解法,不過在本文,我們主要為了講解stream的使用,所以就不去考慮算法的東西了,而如果使用stream,我們就可以寫出下面這樣簡(jiǎn)單易懂的代碼:

          class?Solution?{
          ????public?int[]?topKFrequent(int[]?nums,?int?k)?{
          ????????return?Arrays.stream(nums)
          ?????????????????????.boxed()
          ?????????????????????.collect(Collectors.toMap(e?->?e,?e?->?1,?Integer::sum))
          ?????????????????????.entrySet()
          ?????????????????????.stream()
          ?????????????????????.sorted((m1,?m2)?->?m2.getValue()?-?m1.getValue())
          ?????????????????????.limit(k)
          ?????????????????????.mapToInt(Map.Entry::getKey)
          ?????????????????????.toArray();
          ????}
          }

          總結(jié)

          本文介紹了幾個(gè)簡(jiǎn)單、實(shí)用的stream使用技巧,當(dāng)然stream的應(yīng)用遠(yuǎn)不止此,希望通過本文,能夠激發(fā)起你學(xué)習(xí)stream的興趣,本文若有錯(cuò)誤之處,也歡迎你的指正。

          來源:blog.csdn.net/qq_41698074/article/

          details/108502976

          程序汪資料鏈接

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

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

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

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

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

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


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

          瀏覽 32
          點(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>
                  干女人国产视频 | 蜜桃久久av一区 免费大免费黄在线 | 乱伦小说亚洲图片 | 亚洲电影无码 | 91探花秘 在线播放偷拍 |