一区二区三区三上|欧美在线视频五区|国产午夜无码在线观看视频|亚洲国产裸体网站|无码成年人影视|亚洲AV亚洲AV|成人开心激情五月|欧美性爱内射视频|超碰人人干人人上|一区二区无码三区亚洲人区久久精品

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

JDK8 Stream數(shù)據(jù)流效率分析

Android編程精選 ? 來源:CSDN技術(shù)社區(qū) ? 作者:Al_assad ? 2022-08-17 10:53 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

JDK8 Stream 數(shù)據(jù)流效率分析

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

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

stream 的操作種類

e88aa0fa-1dd0-11ed-ba43-dac502259ad0.png

①中間操作
  • 當(dāng)數(shù)據(jù)源中的數(shù)據(jù)上了流水線后,這個(gè)過程對(duì)數(shù)據(jù)進(jìn)行的所有操作都稱為“中間操作”;
  • 中間操作仍然會(huì)返回一個(gè)流對(duì)象,因此多個(gè)中間操作可以串連起來形成一個(gè)流水線;
  • stream 提供了多種類型的中間操作,如 filterdistinct、mapsorted 等等;
②終端操作
  • 當(dāng)所有的中間操作完成后,若要將數(shù)據(jù)從流水線上拿下來,則需要執(zhí)行終端操作;

  • stream 對(duì)于終端操作,可以直接提供一個(gè)中間操作的結(jié)果,或者將結(jié)果轉(zhuǎn)換為特定的 collection、array、String 等;

stream 的特點(diǎn)

①只能遍歷一次:

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

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

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

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

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

無存儲(chǔ): 流并不存儲(chǔ)值;流的元素源自數(shù)據(jù)源(可能是某個(gè)數(shù)據(jù)結(jié)構(gòu)、生成函數(shù)或I/O通道等等),通過一系列計(jì)算步驟得到;

  • 函數(shù)式風(fēng)格: 對(duì)流的操作會(huì)產(chǎn)生一個(gè)結(jié)果,但流的數(shù)據(jù)源不會(huì)被修改;
  • 惰性求值: 多數(shù)流操作(包括過濾、映射、排序以及去重)都可以以惰性方式實(shí)現(xiàn)。這使得我們可以用一遍遍歷完成整個(gè)流水線操作,并可以用短路操作提供更高效的實(shí)現(xiàn);
  • 無需上界: 不少問題都可以被表達(dá)為無限流(infinite stream):用戶不停地讀取流直到滿意的結(jié)果出現(xiàn)為止(比如說,枚舉 完美數(shù) 這個(gè)操作可以被表達(dá)為在所有整數(shù)上進(jìn)行過濾);集合是有限的,但流可以表達(dá)為無線流;
  • 代碼簡(jiǎn)練: 對(duì)于一些collection的迭代處理操作,使用 stream 編寫可以十分簡(jiǎn)潔,如果使用傳統(tǒng)的 collection 迭代操作,代碼可能十分啰嗦,可讀性也會(huì)比較糟糕;

stream 和 iterator 迭代的效率比較

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

先說結(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ī)約統(tǒng)計(jì)、字符串轉(zhuǎn)化場(chǎng)景下,對(duì)使用 stream 和 iterator 實(shí)現(xiàn)的運(yùn)行效率進(jìn)行了統(tǒng)計(jì)。

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

System:Ubuntu 16.04 xenial

CPUIntel Core i7-8550U

RAM:16GB

JDK version:1.8.0_151

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

JVMSettings:

-Xms1024m

-Xmx6144m

-XX:MaxMetaspaceSize=512m

-XX:ReservedCodeCacheSize=1024m

-XX:+UseConcMarkSweepGC

-XX:SoftRefLRUPolicyMSPerMB=100
1. 映射處理測(cè)試

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

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

e89ec7e2-1dd0-11ed-ba43-dac502259ad0.png

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

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

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

e8b1aaec-1dd0-11ed-ba43-dac502259ad0.png

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

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

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

e8c208ec-1dd0-11ed-ba43-dac502259ad0.png

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

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

//stream
intmax=list.stream()
.mapToInt(x->x)
.max()
.getAsInt();
//iterator
intmax=-1;
for(Integere:list){
if(e>max){
max=e;
}
}
//parallelstream
intmax=list.parallelStream()
.mapToInt(x->x)
.max()
.getAsInt();

e8d37bae-1dd0-11ed-ba43-dac502259ad0.png

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

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

//stream
Stringresult=list.stream().map(String::valueOf).collect(Collectors.joining(","));
//iterator
StringBuilderbuilder=newStringBuilder();
for(Integere:list){
builder.append(e).append(",");
}
Stringresult=builder.length()==0?"":builder.substring(0,builder.length()-1);
//parallelstream
Stringresult=list.stream().map(String::valueOf).collect(Collectors.joining(","));

e8e3f3da-1dd0-11ed-ba43-dac502259ad0.png

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

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

//stream
Listresult=list.stream()
.filter(Objects::nonNull)
.mapToInt(x->x+1)
.filter(x->x>200)
.distinct()
.boxed()
.collect(Collectors.toCollection(ArrayList::new));
//iterator
HashSetset=newHashSet<>(list.size());
for(Integere:list){
if(e!=null&&e>200){
set.add(e+1);
}
}
Listresult=newArrayList<>(set);
//parallelstream
Listresult=list.parallelStream()
.filter(Objects::nonNull)
.mapToInt(x->x+1)
.filter(x->x>200)
.distinct()
.boxed()
.collect(Collectors.toCollection(ArrayList::new));

e8fa4982-1dd0-11ed-ba43-dac502259ad0.png

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

從以上的實(shí)驗(yàn)來看,可以總結(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)幾乎沒有的效率,換來代碼的高可讀性是值得的;

  • 單核 cpu 環(huán)境,不推薦使用 parallel stream,在多核 cpu 且有大數(shù)據(jù)量的條件下,推薦使用 paralle stream

  • stream 中含有裝箱類型,在進(jìn)行中間操作之前,最好轉(zhuǎn)成對(duì)應(yīng)的數(shù)值流,減少由于頻繁的拆箱、裝箱造成的性能損失;

審核編輯:湯梓紅


聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • JAVA
    +關(guān)注

    關(guān)注

    20

    文章

    2988

    瀏覽量

    109416
  • Stream
    +關(guān)注

    關(guān)注

    0

    文章

    21

    瀏覽量

    8127
  • 數(shù)據(jù)流
    +關(guān)注

    關(guān)注

    0

    文章

    125

    瀏覽量

    14860

原文標(biāo)題:Java8 Stream 遍歷數(shù)據(jù)效率差?實(shí)測(cè)結(jié)果出乎意料~~

文章出處:【微信號(hào):AndroidPush,微信公眾號(hào):Android編程精選】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評(píng)論

    相關(guān)推薦
    熱點(diǎn)推薦

    本田數(shù)據(jù)流分析手冊(cè)pdf

    本田數(shù)據(jù)流分析手冊(cè) 
    發(fā)表于 06-15 11:00

    豐田數(shù)據(jù)流分析

    豐田數(shù)據(jù)流分析[此貼子已經(jīng)被作者于2008-6-15 12:00:37編輯過]
    發(fā)表于 06-15 11:03

    奇瑞數(shù)據(jù)流分析手冊(cè)

    奇瑞數(shù)據(jù)流分析手冊(cè) 
    發(fā)表于 06-15 12:02

    日產(chǎn)汽車數(shù)據(jù)流分析

    日產(chǎn)汽車數(shù)據(jù)流分析 
    發(fā)表于 06-15 12:10

    大眾數(shù)據(jù)流分析

    、3.0發(fā)動(dòng)機(jī)數(shù)據(jù)流定義與解釋別克君威2.0發(fā)動(dòng)機(jī)數(shù)據(jù)流定義與解釋凱越數(shù)據(jù)流列表凱越發(fā)動(dòng)機(jī)數(shù)據(jù)流定義賽歐數(shù)據(jù)流列表賽歐
    發(fā)表于 06-15 12:28

    國產(chǎn)汽車數(shù)據(jù)流分析

    汽車數(shù)據(jù)流分析 
    發(fā)表于 06-15 13:10

    基于數(shù)據(jù)流分析與識(shí)別的Web資源訪問控制

    針對(duì)動(dòng)態(tài)Web頁面資源中的實(shí)施細(xì)粒度和透明訪問控制問題,定義片斷的概念,提出基于數(shù)據(jù)流分析的“片斷”級(jí)Web頁面資源的訪問控制方法,分析數(shù)據(jù)流中的請(qǐng)求信息與響應(yīng)片斷的
    發(fā)表于 04-09 09:27 ?23次下載

    基于數(shù)據(jù)流的Java字節(jié)碼分析

    本文基于數(shù)據(jù)流框架理論,提出了如何將數(shù)據(jù)流分析方法應(yīng)用于JAVA 字節(jié)碼中,通過建立數(shù)據(jù)流與半格、數(shù)據(jù)流和函數(shù)調(diào)用圖的關(guān)系,從而對(duì)類型信息進(jìn)
    發(fā)表于 12-25 13:22 ?9次下載

    網(wǎng)絡(luò)數(shù)據(jù)流存儲(chǔ)算法分析與實(shí)現(xiàn)

    針對(duì)網(wǎng)絡(luò)數(shù)據(jù)流存儲(chǔ)的瓶頸問題,提出了一種網(wǎng)絡(luò)數(shù)據(jù)流存儲(chǔ)算法分析與實(shí)現(xiàn)方法,仿真結(jié)果表明,模型能顯著提高網(wǎng)絡(luò)數(shù)據(jù)流的實(shí)時(shí)存儲(chǔ)能力
    發(fā)表于 05-26 15:57 ?21次下載
    網(wǎng)絡(luò)<b class='flag-5'>數(shù)據(jù)流</b>存儲(chǔ)算法<b class='flag-5'>分析</b>與實(shí)現(xiàn)

    基于FPGA芯片的數(shù)據(jù)流結(jié)構(gòu)分析

    Virtex 型FPGA 芯片是Xilinx 公司芯片系列中的一種,Virtex 系列的數(shù)據(jù)流及配置邏輯與XC4000 的數(shù)據(jù)流及配置邏輯有顯著不同,但卻與Xilinx 的FPGA 家族保持了很大
    發(fā)表于 11-18 11:37 ?2654次閱讀

    數(shù)據(jù)流是什么

    數(shù)據(jù)流最初是通信領(lǐng)域使用的概念,代表傳輸中所使用的信息的數(shù)字編碼信號(hào)序列。然而,我們所提到的數(shù)據(jù)流概念與此不同。這個(gè)概念最初在1998年由Henzinger在文獻(xiàn)87中提出,他將數(shù)據(jù)流定義為“只能以事先規(guī)定好的順序被讀取一次的
    的頭像 發(fā)表于 02-27 15:25 ?7445次閱讀

    如何解決JDK8小版本升級(jí)后性能下降的問題

    編者按:在升級(jí) JDK8U 的小版本后(從 8u74 升級(jí)到 8u202),遇到性能劇烈下降的問題(性能下降 13 倍)。該應(yīng)用是一個(gè)非常簡(jiǎn)單的 Web 應(yīng)用,且應(yīng)用在 JDK 升級(jí)前
    的頭像 發(fā)表于 07-26 14:44 ?4520次閱讀
    如何解決<b class='flag-5'>JDK8</b>小版本升級(jí)后性能下降的問題

    Java8Stream map() 方法

    前言 在日常的開發(fā)工作中經(jīng)常碰到要處理 List 中數(shù)據(jù)的問題,比如從一個(gè)對(duì)象集合中獲得對(duì)象中的一個(gè)屬性的集合。之前我們想到的是遍歷每個(gè)元素,然后取出來放到另外一個(gè)集合中,比較繁瑣;在 Java8
    的頭像 發(fā)表于 09-25 11:06 ?2499次閱讀
    Java<b class='flag-5'>8</b>的<b class='flag-5'>Stream</b><b class='flag-5'>流</b> map() 方法

    JDK8升級(jí)JDK11最全實(shí)踐干貨來了

    1、前言 截至目前(2023年),Java8發(fā)布至今已有9年,2018年9月25日,Oracle發(fā)布了Java11,這是Java8之后的首個(gè)LTS版本。那么從JDK8JDK11,到底
    的頭像 發(fā)表于 06-25 14:51 ?901次閱讀
    <b class='flag-5'>JDK8</b>升級(jí)<b class='flag-5'>JDK</b>11最全實(shí)踐干貨來了

    理解ECU數(shù)據(jù)流分析方法

    隨著汽車電子化程度的提高,ECU在車輛中扮演的角色越來越重要。它們不僅控制著發(fā)動(dòng)機(jī)管理、變速箱、制動(dòng)系統(tǒng)等關(guān)鍵功能,還涉及到車輛的舒適性和安全性。 ECU數(shù)據(jù)流分析的重要性 故障診斷 :通過分析
    的頭像 發(fā)表于 11-05 11:07 ?1192次閱讀