<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)雅!

          共 1604字,需瀏覽 4分鐘

           ·

          2022-05-25 00:53

          今日推薦
          答應(yīng)我, 不要再用 if (obj != null) 判空了
          20個(gè)示例!詳解 Java8 Stream 用法,從此告別shi山(垃圾代碼)
          利用Java8新特征,重構(gòu)傳統(tǒng)設(shè)計(jì)模式,你學(xué)會(huì)了嗎?
          竟然有一半的人不知道 for 與 foreach 的區(qū)別???
          利用多線程批量拆分 List 導(dǎo)入數(shù)據(jù)庫,效率杠杠的!

          前言

          雖然 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ì)。

          基本數(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)讲僮鲗懺谝恍猩希珵榱舜a的可讀性,不建議那么做):

          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

          最后,再給大家推薦一個(gè)GitHub項(xiàng)目,該項(xiàng)目整理了上千本常用技術(shù)PDF,技術(shù)書籍都可以在這里找到。
          GitHub地址:https://github.com/hello-go-maker/cs-books
          電子書已經(jīng)更新好了,拿走不謝,記得點(diǎn)一個(gè)star,持續(xù)更新中...

          瀏覽 36
          點(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一二三四区小说 | wwwav| 久久久精品中文字幕麻豆发布 | 波多野结衣一品二品免费观看AV | 人人色人人草 |