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

          JDK8 Stream 效率如何?看了都說好!

          共 6514字,需瀏覽 14分鐘

           ·

          2021-05-15 21:29

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


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

          stream 的操作種類

          ① 中間操作 


          當數據源中的數據上了流水線后,這個過程對數據進行的所有操作都稱為“中間操作”;
          中間操作仍然會返回一個流對象,因此多個中間操作可以串連起來形成一個流水線;
          stream 提供了多種類型的中間操作,如 filter、distinct、map、sorted 等等;


          ②終端操作 


          當所有的中間操作完成后,若要將數據從流水線上拿下來,則需要執(zhí)行終端操作;

          stream 對于終端操作,可以直接提供一個中間操作的結果,或者將結果轉換為特定的 collection、array、String 等;


          這一部分詳細的說明可以參見:JDK8 Stream 詳細使用


          stream 的特點


          ① 只能遍歷一次:


          數據流的從一頭獲取數據源,在流水線上依次對元素進行操作,當元素通過流水線,便無法再對其進行操作,可以重新在數據源獲取一個新的數據流進行操作;


          ② 采用內部迭代的方式:


          對Collection進行處理,一般會使用 Iterator 遍歷器的遍歷方式,這是一種外部迭代;

          而對于處理Stream,只要申明處理方式,處理過程由流對象自行完成,這是一種內部迭代,對于大量數據的迭代處理中,內部迭代比外部迭代要更加高效;

          stream 相對于 Collection 的優(yōu)點


          無存儲


          流并不存儲值;
          流的元素源自數據源(可能是某個數據結構、生成函數或I/O通道等等),通過一系列計算步驟得到;


          函數式風格


          對流的操作會產生一個結果,但流的數據源不會被修改;

          惰性求值

          多數流操作(包括過濾、映射、排序以及去重)都可以以惰性方式實現。
          這使得我們可以用一遍遍歷完成整個流水線操作,并可以用短路操作提供更高效的實現;

          無需上界

          不少問題都可以被表達為無限流(infinite stream):
          用戶不停地讀取流直到滿意的結果出現為止(比如說,枚舉 完美數 這個操作可以被表達為在所有整數上進行過濾);
          集合是有限的,但流可以表達為無線流;

          代碼簡練


          對于一些collection的迭代處理操作,使用 stream 編寫可以十分簡潔,如果使用傳統的 collection 迭代操作,代碼可能十分啰嗦,可讀性也會比較糟糕;



          stream 和 iterator 迭代的效率比較

          好了,上面 stream 的優(yōu)點吹了那么多,stream 函數式的寫法是很舒服,那么 steam 的效率到底怎樣呢?
          先說結論:

          傳統 iterator (for-loop) 比 stream(JDK8) 迭代性能要高,尤其在小數據量的情況下;
          在多核情景下,對于大數據量的處理,parallel stream 可以有比 iterator 更高的迭代處理效率;

          我分別對一個隨機數列 List (數量從 10 到 10000000)進行映射、過濾、排序、規(guī)約統計、字符串轉化場景下,對使用 stream 和 iterator 實現的運行效率進行了統計,測試代碼 基準測試代碼鏈接

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

          System:Ubuntu 16.04 xenial
          CPU:Intel Core i7-8550U
          RAM:16GB
          JDK version1.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. 映射處理測試

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

          //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. 過濾處理測試

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

          //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. 自然排序測試

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

          //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. 歸約統計測試

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

          //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. 字符串拼接測試

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

          //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. 混合操作測試
          對一個隨機數列(List<Integer>)進行去空值,除重,映射,過濾,并組裝為一個新的 List<Integer>,測試的隨機數列容量從 10 - 10000000,跑10次取平均時間;
          //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));

          實驗結果總結

          從以上的實驗來看,可以總結處以下幾點:

          在少低數據量的處理場景中(size<=1000),stream 的處理效率是不如傳統的 iterator 外部迭代器處理速度快的,但是實際上這些處理任務本身運行時間都低于毫秒,這點效率的差距對普通業(yè)務幾乎沒有影響,反而 stream 可以使得代碼更加簡潔;

          在大數據量(szie>10000)時,stream 的處理效率會高于 iterator,特別是使用了并行流,在cpu恰好將線程分配到多個核心的條件下(當然parallel stream 底層使用的是 JVM 的 ForkJoinPool,這東西分配線程本身就很玄學),可以達到一個很高的運行效率,然而實際普通業(yè)務一般不會有需要迭代高于10000次的計算;
          Parallel Stream 受引 CPU 環(huán)境影響很大,當沒分配到多個cpu核心時,加上引用 forkJoinPool 的開銷,運行效率可能還不如普通的 Stream;

          使用 Stream 的建議

          簡單的迭代邏輯,可以直接使用 iterator,對于有多步處理的迭代邏輯,可以使用 stream,損失一點幾乎沒有的效率,換來代碼的高可讀性是值得的;
          單核 cpu 環(huán)境,不推薦使用 parallel stream,在多核 cpu 且有大數據量的條件下,推薦使用 paralle stream;

          stream 中含有裝箱類型,在進行中間操作之前,最好轉成對應的數值流,減少由于頻繁的拆箱、裝箱造成的性能損失;

          源:blog.csdn.net/Al_assad/article/details/82356606

          版權申明:內容來源網絡,版權歸原創(chuàng)者所有。除非無法確認,我們都會標明作者及出處,如有侵權煩請告知,我們會立即刪除并表示歉意。謝謝!





          感謝閱讀



          瀏覽 44
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

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

          手機掃一掃分享

          分享
          舉報
          <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 | 久久99精品久久久久久不卡l中文无码精品 |