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

          JDK 8 Stream 數(shù)據(jù)流效率怎么樣?

          共 7344字,需瀏覽 15分鐘

           ·

          2021-04-10 11:56

          點(diǎn)擊上方藍(lán)色“小哈學(xué)Java”,選擇“設(shè)為星標(biāo)

          回復(fù)“資源”獲取獨(dú)家整理的學(xué)習(xí)資料!


          Stream 是Java SE 8類庫(kù)中新增的關(guān)鍵抽象,它被定義于 java.util.stream (這個(gè)包里有若干流類型:Stream<T> 代表對(duì)象引用流,此外還有一系列特化流,如 IntStream,LongStream,DoubleStream等。

          Java 8 引入的的Stream主要用于取代部分Collection的操作,每個(gè)流代表一個(gè)值序列,流提供一系列常用的聚集操作,可以便捷的在它上面進(jìn)行各種運(yùn)算。集合類庫(kù)也提供了便捷的方式使我們可以以操作流的方式使用集合、數(shù)組以及其它數(shù)據(jù)結(jié)構(gòu);

          stream 的操作種類

          ①中間操作

          • 當(dāng)數(shù)據(jù)源中的數(shù)據(jù)上了流水線后,這個(gè)過(guò)程對(duì)數(shù)據(jù)進(jìn)行的所有操作都稱為“中間操作”;
          • 中間操作仍然會(huì)返回一個(gè)流對(duì)象,因此多個(gè)中間操作可以串連起來(lái)形成一個(gè)流水線;
          • stream 提供了多種類型的中間操作,如 filter、distinct、map、sorted 等等;

          ②終端操作

          • 當(dāng)所有的中間操作完成后,若要將數(shù)據(jù)從流水線上拿下來(lái),則需要執(zhí)行終端操作;
          • stream 對(duì)于終端操作,可以直接提供一個(gè)中間操作的結(jié)果,或者將結(jié)果轉(zhuǎn)換為特定的 collection、array、String 等;

          stream 的特點(diǎn)

          ①只能遍歷一次:

          數(shù)據(jù)流的從一頭獲取數(shù)據(jù)源,在流水線上依次對(duì)元素進(jìn)行操作,當(dāng)元素通過(guò)流水線,便無(wú)法再對(duì)其進(jìn)行操作,可以重新在數(shù)據(jù)源獲取一個(gè)新的數(shù)據(jù)流進(jìn)行操作;

          ②采用內(nèi)部迭代的方式:

          對(duì)Collection進(jìn)行處理,一般會(huì)使用 Iterator 遍歷器的遍歷方式,這是一種外部迭代;

          而對(duì)于處理Stream,只要申明處理方式,處理過(guò)程由流對(duì)象自行完成,這是一種內(nèi)部迭代,對(duì)于大量數(shù)據(jù)的迭代處理中,內(nèi)部迭代比外部迭代要更加高效;

          stream 相對(duì)于 Collection 的優(yōu)點(diǎn)

          stream 和 iterator 迭代的效率比較

          好了,上面 stream 的優(yōu)點(diǎn)吹了那么多,stream 函數(shù)式的寫法是很舒服,那么 steam 的效率到底怎樣呢?

          先說(shuō)結(jié)論:

          • 傳統(tǒng) iterator (for-loop) 比 stream(JDK8) 迭代性能要高,尤其在小數(shù)據(jù)量的情況下;

          - 在多核情景下,對(duì)于大數(shù)據(jù)量的處理,parallel stream 可以有比 iterator 更高的迭代處理效率;

          我分別對(duì)一個(gè)隨機(jī)數(shù)列 List (數(shù)量從 10 到 10000000)進(jìn)行映射、過(guò)濾、排序、規(guī)約統(tǒng)計(jì)、字符串轉(zhuǎn)化場(chǎng)景下,對(duì)使用 stream 和 iterator 實(shí)現(xiàn)的運(yùn)行效率進(jìn)行了統(tǒng)計(jì),測(cè)試代碼 基準(zhǔn)測(cè)試代碼鏈接。

          測(cè)試環(huán)境如下:

          System:Ubuntu 16.04 xenial

          CPU:Intel Core i7-8550U

          RAM:16GB

          JDK version:1.8.0_151

          JVM:HotSpot(TM) 64-Bit Server VM (build 25.151-b12, mixed mode)

          JVM Settings:

              -Xms1024m

              -Xmx6144m

              -XX:MaxMetaspaceSize=512m

              -XX:ReservedCodeCacheSize=1024m

              -XX:+UseConcMarkSweepGC

              -XX:SoftRefLRUPolicyMSPerMB=100

          1. 映射處理測(cè)試

          把一個(gè)隨機(jī)數(shù)列(List<Integer>)中的每一個(gè)元素自增1后,重新組裝為一個(gè)新的 List<Integer>,測(cè)試的隨機(jī)數(shù)列容量從 10 - 10000000,跑10次取平均時(shí)間;

          //stream
          List<Integer> result = list.stream()
          .mapToInt(x -> x)
          .map(x -> ++x)
          .boxed()
          .collect(Collectors.toCollection(ArrayList::new));
          //iterator
          List<Integer> result = new ArrayList<>();
          for(Integer e : list){
              result.add(++e);
          }
          //parallel stream
          List<Integer> result = list.parallelStream()
          .mapToInt(x -> x)
          .map(x -> ++x)
          .boxed()
          .collect(Collectors.toCollection(ArrayList::new));

          2. 過(guò)濾處理測(cè)試

          取出一個(gè)隨機(jī)數(shù)列(List<Integer>)中的大于 200 的元素,并組裝為一個(gè)新的 List<Integer>,測(cè)試的隨機(jī)數(shù)列容量從 10 - 10000000,跑10次取平均時(shí)間;

          //stream
          List<Integer> result = list.stream()
          .mapToInt(x -> x)
          .filter(x -> x > 200)
          .boxed()
          .collect(Collectors.toCollection(ArrayList::new));
          //iterator
          List<Integer> result = new ArrayList<>(list.size());
          for(Integer e : list){
              if(e > 200){
                  result.add(e);
              }
          }
          //parallel stream
          List<Integer> result = list.parallelStream()
          .mapToInt(x -> x)
          .filter(x -> x > 200)
          .boxed()
          .collect(Collectors.toCollection(ArrayList::new));

          3. 自然排序測(cè)試

          對(duì)一個(gè)隨機(jī)數(shù)列(List<Integer>)進(jìn)行自然排序,并組裝為一個(gè)新的 List<Integer>,iterator 使用的是 Collections # sort API(使用歸并排序算法實(shí)現(xiàn)),測(cè)試的隨機(jī)數(shù)列容量從 10 - 10000000,跑10次取平均時(shí)間;

          //stream
          List<Integer> result = list.stream()
          .mapToInt(x->x)
          .sorted()
          .boxed()
          .collect(Collectors.toCollection(ArrayList::new));
          //iterator
          List<Integer> result = new ArrayList<>(list);
          Collections.sort(result);
          //parallel stream
          List<Integer> result = list.parallelStream()
          .mapToInt(x->x)
          .sorted()
          .boxed()
          .collect(Collectors.toCollection(ArrayList::new));

          4. 歸約統(tǒng)計(jì)測(cè)試

          獲取一個(gè)隨機(jī)數(shù)列(List<Integer>)的最大值,測(cè)試的隨機(jī)數(shù)列容量從 10 - 10000000,跑10次取平均時(shí)間;

          //stream
          int max = list.stream()
          .mapToInt(x -> x)
          .max()
          .getAsInt();
          //iterator
          int max = -1;
          for(Integer e : list){
              if(e > max){
                  max = e;
              }
          }
          //parallel stream
          int max = list.parallelStream()
          .mapToInt(x -> x)
          .max()
          .getAsInt();

          5. 字符串拼接測(cè)試

          獲取一個(gè)隨機(jī)數(shù)列(List<Integer>)各個(gè)元素使用“,”分隔的字符串,測(cè)試的隨機(jī)數(shù)列容量從 10 - 10000000,跑10次取平均時(shí)間;

            //stream
          String result = list.stream().map(String::valueOf).collect(Collectors.joining(","));
          //iterator
          StringBuilder builder = new StringBuilder();
          for(Integer e : list){
              builder.append(e).append(",");
          }
          String result = builder.length() == 0 ? "" : builder.substring(0,builder.length() - 1);
          //parallel stream
          String result = list.stream().map(String::valueOf).collect(Collectors.joining(","));

          6. 混合操作測(cè)試

          對(duì)一個(gè)隨機(jī)數(shù)列(List<Integer>)進(jìn)行去空值,除重,映射,過(guò)濾,并組裝為一個(gè)新的 List<Integer>,測(cè)試的隨機(jī)數(shù)列容量從 10 - 10000000,跑10次取平均時(shí)間;

          //stream
          List<Integer> result = list.stream()
          .filter(Objects::nonNull)
          .mapToInt(x -> x + 1)
          .filter(x -> x > 200)
          .distinct()
          .boxed()
          .collect(Collectors.toCollection(ArrayList::new));
          //iterator
          HashSet<Integer> set  = new HashSet<>(list.size());
          for(Integer e : list){
              if(e != null && e > 200){
                  set.add(e + 1);
              }
          }
          List<Integer> result = new ArrayList<>(set);
          //parallel stream
          List<Integer> result = list.parallelStream()
          .filter(Objects::nonNull)
          .mapToInt(x -> x + 1)
          .filter(x -> x > 200)
          .distinct()
          .boxed()
          .collect(Collectors.toCollection(ArrayList::new));

          實(shí)驗(yàn)結(jié)果總結(jié)

          從以上的實(shí)驗(yàn)來(lái)看,可以總結(jié)處以下幾點(diǎn):

          • 在少低數(shù)據(jù)量的處理場(chǎng)景中(size<=1000),stream 的處理效率是不如傳統(tǒng)的 iterator 外部迭代器處理速度快的,但是實(shí)際上這些處理任務(wù)本身運(yùn)行時(shí)間都低于毫秒,這點(diǎn)效率的差距對(duì)普通業(yè)務(wù)幾乎沒有影響,反而 stream 可以使得代碼更加簡(jiǎn)潔;
          • 在大數(shù)據(jù)量(szie>10000)時(shí),stream 的處理效率會(huì)高于 iterator,特別是使用了并行流,在cpu恰好將線程分配到多個(gè)核心的條件下(當(dāng)然parallel stream 底層使用的是 JVM 的 ForkJoinPool,這東西分配線程本身就很玄學(xué)),可以達(dá)到一個(gè)很高的運(yùn)行效率,然而實(shí)際普通業(yè)務(wù)一般不會(huì)有需要迭代高于10000次的計(jì)算;
          • Parallel Stream 受引 CPU 環(huán)境影響很大,當(dāng)沒分配到多個(gè)cpu核心時(shí),加上引用 forkJoinPool 的開銷,運(yùn)行效率可能還不如普通的 Stream;

          使用 Stream 的建議

          • 簡(jiǎn)單的迭代邏輯,可以直接使用 iterator,對(duì)于有多步處理的迭代邏輯,可以使用 stream,損失一點(diǎn)幾乎沒有的效率,換來(lái)代碼的高可讀性是值得的;
          • 單核 cpu 環(huán)境,不推薦使用 parallel stream,在多核 cpu 且有大數(shù)據(jù)量的條件下,推薦使用 paralle stream;
          • stream 中含有裝箱類型,在進(jìn)行中間操作之前,最好轉(zhuǎn)成對(duì)應(yīng)的數(shù)值流,減少由于頻繁的拆箱、裝箱造成的性能損失;

          原文鏈接:https://blog.csdn.net/Al_assad/article/details/82356606

          版權(quán)聲明:本文為CSDN博主「Al_assad」的原創(chuàng)文章,遵循CC 4.0 BY-SA版權(quán)協(xié)議,轉(zhuǎn)載請(qǐng)附上原文出處鏈接及本聲明。

          1. 又發(fā)現(xiàn)一款牛逼的 API 敏捷開發(fā)工具

          2. 發(fā)現(xiàn)一個(gè)很奇怪的現(xiàn)象,MyBaits 的 insert方法一直返回"-2147482646"

          3. 翻車!在項(xiàng)目中用了Arrays.asList、ArrayList的subList,被公開批評(píng)

          4. MySQL高頻面試題,硬gang面試官

          最近面試BAT,整理一份面試資料Java面試BATJ通關(guān)手冊(cè),覆蓋了Java核心技術(shù)、JVM、Java并發(fā)、SSM、微服務(wù)、數(shù)據(jù)庫(kù)、數(shù)據(jù)結(jié)構(gòu)等等。

          獲取方式:點(diǎn)“在看”,關(guān)注公眾號(hào)并回復(fù) Java 領(lǐng)取,更多內(nèi)容陸續(xù)奉上。

          文章有幫助的話,在看,轉(zhuǎn)發(fā)吧。

          謝謝支持喲 (*^__^*)

          瀏覽 19
          點(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>
                  天天操天天拍 | 精品国产精品国产精品 | 毛片十八| 骚在线视频 | 亚洲午夜精品久久久 |