searchsearch

www.hkeasychat.com

再來看看Java的新特性€€€€Stream流 - 手機數碼電腦討論區

登入     註冊



再來看看Java的新特性€€€€Stream流

笑看人生458發表於 2020-7-16 21:25:02

推薦閱讀︰
性能優化專題復習︰JVM+Tomcat+MySQL+面試+學習筆記等



半年前開始試著使用Java的新特性,給我印象最深的就是Stream流和Optional。其中Stream提高了看法效率,讓代碼看起來十分清爽。

再來看看Java的新特性€€€€Stream流

01 為什麼要使用流?

摘要中已經說明了,為了提高開發效率。流可以幫助我們高效操作集合,流幫助我們通過流水線的方式對集合進行刪減、合並、排序、修改,並最終返回我們想要的元素數據或統計數據。流水線的意思是說,一批元素不需要等待全部元素都完成某步操作,才進行下步操作,而是可以盡早進行下步操作,就好像流水線工廠一樣,這為流高效運作提供了基礎。流還有一個內部迭代的概念,就是把for循環顯示迭代隱藏起來了,這樣可以更方便的並行開發。

02 流的使用

2.1 準備

在使用流之前需要做些準備,首先說明兩個概念︰中間操作 和 終端操作。中間操作就好比生產車間的一步一步元素處理,每步處理之後,里面的元素樣式或者數據結構可能發生改變了,但是它還是流。終端操作就好比產品生產完了,要打包裝箱,變成最終消費者可見的最終形態,此時,它已經是產品,不再是流了。

接著為了演示操作,先模擬幾條數據
List<JSONObject> menu = new ArrayList<>();menu.add(new JSONObject().putOpt("name","宮保雞丁").putOpt("price","28"));menu.add(new JSONObject().putOpt("name","魚香肉絲").putOpt("price","30"));menu.add(new JSONObject().putOpt("name","肉夾饃").putOpt("price","6"));menu.add(new JSONObject().putOpt("name","煎餅").putOpt("price","6"));
2.2 常用的中間操作

(1)filter

filter應該是Stream操作里面最常見的了,過濾器顧名思義就是過濾數據用的,filter的參數可以是lambda表達式。
//比如下面這句話,就是得到所有價格小于10的食物,得到的還是流。//stream()方法將集合轉成流menu.stream().filter(jsonObject -> jsonObject.getInt("price")<10);
(2)distinct 、 limit 和 skip

distinct是去重,limit是截取前幾個元素,skip是跳過前多少個元素。
List<Integer> integerList = new ArrayList<>();integerList.add(1);integerList.add(1);integerList.add(2);integerList.add(3);integerList.stream() .distinct()//經過去重,流還剩1、2、3 .skip(1)//跳過第一個元素,流中還有2、3 .limit(1);//截取第一個元素,流中還剩2
(3)map

map映射,上面的filter是將元素篩選,map則是改變元素的樣式。比如,我們想要知道所有小于10塊食物的名字。
menu.stream() .filter(jsonObject -> jsonObject.getInt("price")<10)//此時還是jsonObject        .map(jsonObject -> jsonObject.getStr("name"));//此時變成了String
(4)flatMap

流的合並,可以將多個數組合並操作,這樣返回元素不是流,而是具體元素本身了。
Stream.of(menu,foreignMenu)//此時元素是流 List<Stream> .flatMap(x -> x.stream())//此時元素是jsonObject List<jsonObject> .map(jsonObject -> jsonObject.getStr("name")) .distinct();
2.3 常用的終端方法

(1)allMatch、anyMatch、noneMatch、findFirst和findAny

方法 含義 allMatch 檢查謂詞是否匹配所有元素 anyMatch 檢查謂詞是否至少匹配一個元素 noneMatch 確保流中沒有任何元素與給定的謂詞匹配 findFirst 查找第一個符合條件的元素 findAny 將返回當前流中的任意元素
//前三個方法都是返回boolean類型boolean allMatchBool = menu.stream() .allMatch(jsonObject -> jsonObject.getInt("price") < 10);boolean noneMatchBool = menu.stream() .noneMatch(jsonObject -> jsonObject.getInt("price") < 10);boolean anyMatchBool = menu.stream() .anyMatch(jsonObject -> jsonObject.getInt("price") < 10);
上面個方法返回的都是boolean類型,findFirst、findAny返回的都是元素。
//關于Optional,先不關心,總之是元素就對了Optional<JSONObject> first = menu.stream().findFirst();Optional<JSONObject> any = menu.stream().findAny();System.out.println(first.get().toString());System.out.println(any.get().toString());//輸出//{"price":"28","name":"宮保雞丁"}//{"price":"28","name":"宮保雞丁"}
以上兩個方法,只要找到符合條件的數據,流就提前結束了。為什麼都是輸出第一個元素,卻要實現有兩個方法呢?因為並行,findAny在並行方面限制會少一些。

(2)reduce

最開始的時候說了,最終的返回值可以是元素集合,也可以是統計數據(或者說歸納),比如說元素求和。假設我們需要menu中所有食品各要一份需要花多少錢。
Optional<Integer> price = menu.stream()//List<JsonObject> .map(jsonObject -> jsonObject.getInt("price"))//先將元素轉成數字List<Integer> .reduce((x, y) -> x + y);System.out.println(price.get());
(3)max和min

這個好理解,就是最大值和最小值嘛。效果類似于
.reduce(Integer::max).reduce(Integer::min)
2.4 常用流匯總

再來看看Java的新特性€€€€Stream流

其中沒有展示sorted、count這個都好理解。至于collect這個後面講,用的比較多。

2.5 流的轉化

除了對象流(Stream)以外,還有一些類型流,比如說 IntStream(以 IntStream 舉例,其他類似)上面求和返回的是Optional對象,那可以直接返回Integer類型嗎?
//使用映射方法mapToInt()就ok了int price = menu.stream()//Stream .mapToInt(jsonObject -> jsonObject.getInt("price"))//IntStream .sum();//類型流轉化回對象流,可以使用boxed()IntStream intStream = menu.stream()        .mapToInt(jsonObject -> jsonObject.getInt("price"));Stream<Integer> boxed = intStream.boxed();//當然了IntStream中有很多int類型操作的方法,就不一一舉例了,源碼打開一看,見名知意
03 收集器

前面講的常用的中間操作,返回值都是流,還有一些中斷操作,返回值都是Optional或者數值。可別忘了Stream最開始的初衷是為了解決集合操作問題。最終轉化成集合使用的中斷操作collect,參數是接口 Collector,里面有眾多轉化方法。

3.1 轉換成集合

最常用的莫非toList() 這個方法了,將返回結果變成List。
List<JSONObject> list = menu.stream() .filter(jsonObject -> jsonObject.getInt("price") < 10) .collect(Collectors.toList());//當然還有toSet()等等,觸類旁通
3.2 字符串拼接

比較常用,就是字符串鏈接了。使用joining()方法
String s = menu.stream() .filter(jsonObject -> jsonObject.getInt("price") < 10) .map(jsonObject -> jsonObject.getStr("name")) .collect(Collectors.joining(","));
3.3 分組

根據提供的屬性分組,使用 groupingBy() ,為了方便說明,給上面各種食品一個type值︰
List<JSONObject> menu = new ArrayList<>();menu.add(new JSONObject().putOpt("name","宮保雞丁").putOpt("price","28").putOpt("type","good"));menu.add(new JSONObject().putOpt("name","魚香肉絲").putOpt("price","30").putOpt("type","good"));menu.add(new JSONObject().putOpt("name","肉夾饃").putOpt("price","6").putOpt("type","normal"));menu.add(new JSONObject().putOpt("name","煎餅").putOpt("price","6").putOpt("type","normal"));Map<String, List<JSONObject>> type = menu.stream() .collect(Collectors.groupingBy(jsonObject -> jsonObject.getStr("type")));System.out.println(type);//輸出//{normal=[{"price":"6","name":"肉夾饃","type":"normal"}, {"price":"6","name":"煎餅","type":"normal"}], good=[{"price":"28","name":"宮保雞丁","type":"good"}, {"price":"30","name":"魚香肉絲","type":"good"}]}
與分組類似的還有一個方法 partitioningBy (),分區,不過它的參數位于是boolean類型。


作者︰啤酒就辣條
原文鏈接︰https://juejin.im/post/5dcffde5f265da0bc40cedae


作者:追逐仰望星空

相關內容:
上一篇:華為翻身神作,從5999到2999,256G遺憾淪為退場價!
下一篇:推薦個行車記錄儀唄,三百左右的?

更多帖子推薦

手機數碼電腦討論區最新帖子快速翻頁:
234567891011121314151617

手機數碼電腦討論區

再來看看Java的新特性€€€€Stream流 -END- 

香港交友討論區hkeasychat - 香港社交論壇forum本交友論壇採用forum形式運作,會員所講所post交友話題、發起的交友活動與本交友網立場無關 本頁面任何內容(包括但不限於:『留言、文章』)不代表廣告商同意立場及觀點,本頁面可能出現間接宣傳。hkeasychat旗下討論區業務集團之一 - hkeasychat 香港交友討論區 聯絡我們