java stream 原理

java stream 原理

需求
從"Apple" "Bug" "ABC" "Dog"中選出以A開頭的名字,然后從中選出最長的一個,并輸出其長度

1. 最直白的實現

Github

缺點
  1. 迭代次數過多
  2. 頻繁產生中間結果,性能無法接受

2. 平常寫法

int longest = 0;
for(String str : strings){if(str.startsWith("A")){// 1. filter(), 保留以張開頭的字符串int len = str.length();// 2. mapToInt(), 轉換成長度longest = Math.max(len, longest);// 3. max(), 保留最長的長度}
}
System.out.println(longest);
缺點
  1. 具體業務與算法混在一起,不利于代碼復用
  2. 耦合性太強,代碼不清晰

3. 責任鏈模式解耦

public interface Chain {void proceed(Object object);
}
public class ForChain implements Chain {private final Chain chain;public ForChain(Chain chain){this.chain = chain;}@Overridepublic void proceed(Object object) {List<String> list = (List<String>) object;for(String a : list){if(a.startsWith("A"))chain.proceed(a);}}
}
public class LengthChain implements Chain {private final Chain chain;public LengthChain(Chain chain){this.chain = chain;}@Overridepublic void proceed(Object object) {String string = (String)object;chain.proceed(string.length());}
}
public class ResultChain implements Chain {private Integer result = 0;@Overridepublic void proceed(Object object) {Integer integer = (Integer) object;result = Math.max(integer,result);}public Integer getResult() {return result;}
}
public class Client {public static void main(String[] args) {ResultChain resultChain = new ResultChain();LengthChain lengthChain = new LengthChain(resultChain);ForChain forChain = new ForChain(lengthChain);List<String> list = Arrays.asList("Apple","Bug","ABC","Dog");forChain.proceed(list);System.out.println("result is "+ resultChain.getResult());}
}

4. java stream 實現

OptionalInt max = Stream.of("Apple", "Bug", "ABC", "Dog").filter(e -> e.startsWith("A")).mapToInt(e -> e.length()).max();
System.out.println("result is "+ max.getAsInt());
優點
  1. 開發者是需要關注具體的業務,頂層算法都封裝在框架中
  2. 代碼結構清晰,代碼量少,減少出錯的機會

5. Stream 的原理

5.1 stream與集合比較

盡管stream與集合框架在表現上非常相似,二者都是對數據進行處理,但事實上二者完全不同。集合是一種數據結構,主要關注在內存中組織數據,會在一段時間在內存中持續的存在,而流的主要關注在計算,不為數據提供任何存儲空間,只會通過管道提供計算結果。

5.2 stream 操作分類

stream分類

中間操作:返回一個新的stream

  • 有狀態:必須等上一步操作完,才能執行下一步操作
  • 無狀態:該操作不受上一步操作的影響

終止操作:返回結果

  • 短路:找到即返回
  • 費短路:遍歷所有元素

以上操作決定了Stream一定是先構建完畢再執行的特點,也就是延遲執行,當需要結果(終端操作時)開始執行流水線。

5.3 stream 結構示意圖

stream結構示意圖

5.4 操作如何記錄
  • Head記錄起始操作
  • StateLessOp記錄中間操作
  • StatefulOp記錄有狀態的中間操作

這三個操作,在實例化的時候回指向前一個操作,和后一個操作,形成雙向鏈表,每一步操作都能得知上一步和下一步操作。

對于Head:

AbstractPipeline(Spliterator<?> source,int sourceFlags, boolean parallel) {this.previousStage = null;this.sourceSpliterator = source;this.sourceStage = this;this.sourceOrOpFlags = sourceFlags & StreamOpFlag.STREAM_MASK;// The following is an optimization of:// StreamOpFlag.combineOpFlags(sourceOrOpFlags, StreamOpFlag.INITIAL_OPS_VALUE);this.combinedFlags = (~(sourceOrOpFlags << 1)) & StreamOpFlag.INITIAL_OPS_VALUE;this.depth = 0;this.parallel = parallel;
}

對于其他操作:

AbstractPipeline(AbstractPipeline<?, E_IN, ?> previousStage, int opFlags) {if (previousStage.linkedOrConsumed)throw new IllegalStateException(MSG_STREAM_LINKED);previousStage.linkedOrConsumed = true;previousStage.nextStage = this; // 構造雙向鏈表this.previousStage = previousStage;this.sourceOrOpFlags = opFlags & StreamOpFlag.OP_MASK;this.combinedFlags = StreamOpFlag.combineOpFlags(opFlags, previousStage.combinedFlags);this.sourceStage = previousStage.sourceStage;if (opIsStateful())sourceStage.sourceAnyStateful = true;this.depth = previousStage.depth + 1;
}

例子:

data.stream()
.filter(x -> x.length() == 2)
.map(x -> x.replace(“三”,”五”))
.sorted()
.filter(x -> x.contains(“五”))
.forEach(System.out::println);

Stage
stage

5.5 操作如何疊加

從終止操作依次構造Sink,如此Sink鏈構造完成

final <P_IN> Sink<P_IN> wrapSink(Sink<E_OUT> sink) {Objects.requireNonNull(sink);// 依次構造sinkfor ( @SuppressWarnings("rawtypes") AbstractPipeline p=AbstractPipeline.this; p.depth > 0; p=p.previousStage) {sink = p.opWrapSink(p.previousStage.combinedFlags, sink);}return (Sink<P_IN>) sink;}

sink
sink

  1. 依次調用sink的begin方法,通知sink鏈數據已準備好
  2. 依次調用sink的accept方法,處理數據
  3. 依次調用sink的end方法,通知數據處理完畢
@Override
final <P_IN> void copyInto(Sink<P_IN> wrappedSink, Spliterator<P_IN> spliterator) {Objects.requireNonNull(wrappedSink);if (!StreamOpFlag.SHORT_CIRCUIT.isKnown(getStreamAndOpFlags())) {wrappedSink.begin(spliterator.getExactSizeIfKnown());spliterator.forEachRemaining(wrappedSink);wrappedSink.end();}else {copyIntoWithCancel(wrappedSink, spliterator);}
}

accept

5.6 如何收集結果

對于forEach是不需要收集結果的,對于collect結果保存在最后一個sink中,這樣的操作都會提供一個get方法取出數據。終止操作都會實現Supplier的get方法

@Override
public <P_IN> R evaluateSequential(PipelineHelper<T> helper,Spliterator<P_IN> spliterator) {return helper.wrapAndCopyInto(makeSink(), spliterator).get();
}
public interface Supplier<T> {/*** Gets a result.** @return a result*/T get();
}
interface TerminalSink<T, R> extends Sink<T>, Supplier<R> { }

轉載于:https://www.cnblogs.com/dragonfei/p/8710240.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/252026.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/252026.shtml
英文地址,請注明出處:http://en.pswp.cn/news/252026.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

ubuntu文本模式獲得權限修改profile

針對ubuntu14.04以下&#xff0c;越舊版本&#xff0c;舊的指令也有效。 進入登錄頁面&#xff0c;按shiftaltF1進入root環境&#xff0c;驗證用戶名密碼。 然后輸入&#xff1a;cd /etc 進入etc文件 在輸入&#xff1a;/usr/bin/sudo vi profile 進入profile文件的文本編輯模…

here文檔 here doc EOF重定向

here文檔 here doc EOF重定向 http://www.cnblogs.com/xiangzi888/archive/2012/03/24/2415077.html 在shell腳本程序中&#xff0c;向一條命令傳遞輸入的一種特殊方法是使用here文檔。一個here document就是一段帶有特殊目的的代碼段。它使用I/O重定向的形式將一個命令序列傳…

Java常量池理解與總結

2019獨角獸企業重金招聘Python工程師標準>>> 一.相關概念 什么是常量用final修飾的成員變量表示常量&#xff0c;值一旦給定就無法改變&#xff01;final修飾的變量有三種&#xff1a;靜態變量、實例變量和局部變量&#xff0c;分別表示三種類型的常量。Class文件中…

轉載:https://blog.csdn.net/dcrmg/article/details/52939318

張正友相機標定Opencv實現以及標定流程&&標定結果評價&&圖像矯正流程解析&#xff08;附標定程序和棋盤圖&#xff09;使用Opencv實現張正友法相機標定之前&#xff0c;有幾個問題事先要確認一下&#xff0c;那就是相機為什么需要標定&#xff0c;標定需要的輸…

Redis學習筆記--Redis數據過期策略詳解==轉

本文對Redis的過期機制簡單的講解一下  講解之前我們先拋出一個問題&#xff0c;我們知道很多時候服務器經常會用到redis作為緩存&#xff0c;有很多數據都是臨時緩存一下&#xff0c;可能用過之后很久都不會再用到了&#xff08;比如暫存session&#xff0c;又或者只存放日行…

會員連鎖配置以及金額走向

PS&#xff1a;所有電子支付方式的資金走向都是同樣的&#xff0c;配置的是什么支付方式就走什么支付方式;下面以支付寶為例說明 一、連鎖非總機模式 資金走向&#xff1a; 支付寶&#xff1a;收到的錢在主賬號配置的支付寶&#xff0c;會員卡的金額在主賬號 微信&#xff1a;收…

Python標準模塊--logging

Python標準模塊--logging參考http://www.cnblogs.com/zhbzz2007/p/5943685.html1 logging模塊簡介logging模塊是Python內置的標準模塊&#xff0c;主要用于輸出運行日志&#xff0c;可以設置輸出日志的等級、日志保存路徑、日志文件回滾等&#xff1b;相比print&#xff0c;具備…

Podfile grammar

參考&#xff1a;http://www.jianshu.com/p/8af475c4f717 Podfile Podfile文件詳細描述了一個或多個工程中targets的依賴關系。Podfile會默認創建一個隱式的目標鏈接到工程中用戶的第一個target&#xff0c;名稱為“default”。 一個Podfile可以非常簡單: *pod AFNetworking, ~…

并發編程 - 協程 - 1.協程概念/2.greenlet模塊/3.gevent模塊/4.gevent實現并發的套接字通信...

1.協程并發&#xff1a;切保存狀態單線程下實現并發&#xff1a;協程 切 保存狀態 yield 遇到io切&#xff0c;提高效率 遇到計算切&#xff0c;并沒有提高效率 檢測單線程下 IO行為 io阻塞 切 相當于騙操作系統 一直處于計算協程&#xff1a;。。。單線程下實現…

pymysql

連接數據庫 連接時需要額外指定參數dbcursor.execute( ) 操作SQL語句SELECT VERSION() 獲得當前版本CREATE DATABASE spiders DEFAULT CHARACTER SET utf8 創建數據庫import pymysql db pymysql.connect(hostlocalhost,user ,password ,port3306)#IP&#xff0c;用戶名&#x…

C# 多線程及同步簡介示例

60年代&#xff0c;在OS中能擁有資源和獨立運行的基本單位是進程&#xff0c;然而隨著計算機技術的發展&#xff0c;進程出現了很多弊端&#xff0c;一是由于進程是資源擁有者&#xff0c;創建、撤消與切換存在較大的時空開銷&#xff0c;因此需要引入輕型進程&#xff1b;二是…

opencv-python單目視覺標定,簡單易用。

import cv2 import numpy as np import glob# 設置尋找亞像素角點的參數&#xff0c;采用的停止準則是最大循環次數30和最大誤差容限0.001 criteria (cv2.TERM_CRITERIA_MAX_ITER | cv2.TERM_CRITERIA_EPS, 30, 0.001)# 獲取標定板角點的位置 objp np.zeros((6 * 7, 3), np.f…

python多線程多進程

一、線程&進程 對于操作系統來說&#xff0c;一個任務就是一個進程&#xff08;Process&#xff09;&#xff0c;比如打開一個瀏覽器就是啟動一個瀏覽器進程&#xff0c;打開一個記事本就啟動了一個記事本進程&#xff0c;打開兩個記事本就啟動了兩個記事本進程&#xff0c…

Spring Framework 5.1.6、5.0.13 與?4.3.23 發布

開發四年只會寫業務代碼&#xff0c;分布式高并發都不會還做程序員&#xff1f; Spring Framework 5.1.6、5.0.13 與 4.3.23 發布了。 v5.1.6 包含 49 個 bug 修復和功能改進&#xff1b;v5.0.13 是 5.0.x 系列的最后一個版本&#xff0c;包含了 25 個 bug 修復和功能改進&am…

curl命令

Curl是一種支持多種協議&#xff08;http、https&#xff0c;ftp&#xff09;等&#xff0c;利用url規則在命令行下工作的文件傳輸工具&#xff0c;還支持POST、cookies、認證、從指定偏移處下載部分文件、用戶代理字符串、限速、文件大小、進度條等特征 1.語法&#xff1a; cu…

單目視覺標定:世界坐標系、相機坐標系、圖像坐標系、像素坐標系——簡單粗暴,粗暴

轉&#xff1a;https://blog.csdn.net/chentravelling/article/details/53558096 1.正文 圖像處理、立體視覺等等方向常常涉及到四個坐標系&#xff1a;世界坐標系、相機坐標系、圖像坐標系、像素坐標系。例如下圖&#xff1a; 構建世界坐標系只是為了更好的描述相機的位置在哪…

Python基礎知識-05-數據類型總結字典

python其他知識目錄 1、一道題&#xff0c;選擇商品的序號。程序員和用戶各自面對的序號起始值 如有變量 googs [汽車,飛機,火箭] 提示用戶可供選擇的商品&#xff1a; 0,汽車1,飛機2,火箭用戶輸入索引后&#xff0c;將指定商品的內容拼接打印&#xff0c;如&#xff1a;用戶輸…

Python學習筆記之異常

Python用異常對象來表示異常情況&#xff0c;如果異常對象未被處理或捕捉&#xff0c;程序就會回溯&#xff08;traceback&#xff09;中止執行。 異常可以在出錯時自動引發&#xff0c;也可以主動引發。 異常被引發后如果不被處理就會傳播至程序調用的地方&#xff0c;直到主程…

VSFTP的使用

一、基本安裝 1.安裝服務 yum -y install vsftpd //centos Redhat apt-get install vsftpd //debian ubuntu 2.開啟服務 service vsftpd status //查看狀態&#xff0c;默認是關閉的 service vsftpd start 3.開機隨操作系統啟動 chkconfig vsftpd on4.添加賬號 useradd -d /…

OC Swift混編-Swift.h File not found

https://www.jianshu.com/p/f860fe1718ca 2016.09.13 11:53* 字數 266 閱讀 1935評論 1喜歡 1今天碰到個神坑,本人項目是OC項目,最近開始使用Swift開始替代.但是,在替代的已開始就出現問題了:新建swift文件,然后提示創建bridging-Hearder文件,然后swift可以使用OC代碼了.這些都…