恕我直言你可能真的不會java第5篇:Stream的狀態與並行操做

1、回顧Stream管道流操做


經過前面章節的學習,咱們應該明白了Stream管道流的基本操做。咱們來回顧一下:vue

  • 源操做:能夠將數組、集合類、行文本文件轉換成管道流Stream進行數據處理
  • 中間操做:對Stream流中的數據進行處理,好比:過濾、數據轉換等等
  • 終端操做:做用就是將Stream管道流轉換爲其餘的數據類型。這部分咱們尚未講,咱們後面章節再介紹。

看下面的腦圖,能夠有更清晰的理解:java

2、中間操做:有狀態與無狀態

其實在程序員編程中,常常會接觸到「有狀態」,「無狀態」,絕大部分的人都比較蒙。並且在不一樣的場景下,「狀態」這個詞的含義彷佛有所不一樣。可是「萬變不離其宗」,理解「狀態」這個詞在編程領域的含義,筆者教給你們幾個關鍵點:程序員

  • 狀態一般表明公用數據,有狀態就是有「公用數據」
  • 由於有公用的數據,狀態一般須要額外的存儲。
  • 狀態一般被多人、多用戶、多線程、屢次操做,這就涉及到狀態的管理及變動操做。

是否是更蒙了?舉個例子,你就明白了web

  • web開發session就是一種狀態,訪問者的屢次請求關聯同一個session,這個session須要存儲到內存或者redis。屢次請求使用同一個公用的session,這個session就是狀態數據。
  • vue的vuex的store就是一種狀態,首先它是多組件公用的,其次是不一樣的組件均可以修改它,最後它須要獨立於組件單獨存儲。因此store就是一種狀態。

回到咱們的Stream管道流redis

  • filter與map操做,不須要管道流的前面後面元素相關,因此不須要額外的記錄元素之間的關係。輸入一個元素,得到一個結果。
  • sorted是排序操做、distinct是去重操做。像這種操做都是和別的元素相關的操做,我本身沒法完成總體操做。就像班級點名就是無狀態的,喊到你你就答到就能夠了。若是是班級同窗按大小個排序,那就不是你本身的事了,你得和周圍的同窗比一下身高並記住,你記住的這個身高比較結果就是一種「狀態」。因此這種操做就是有狀態操做。

3、Limit與Skip管道數據截取

List<String> limitN = Stream.of("Monkey", "Lion", "Giraffe", "Lemur")
        .limit(2)
        .collect(Collectors.toList());
List<String> skipN = Stream.of("Monkey", "Lion", "Giraffe", "Lemur")
        .skip(2)
        .collect(Collectors.toList());
  • limt方法傳入一個整數n,用於截取管道中的前n個元素。通過管道處理以後的數據是:[Monkey, Lion]。
  • skip方法與limit方法的使用相反,用於跳過前n個元素,截取從n到末尾的元素。通過管道處理以後的數據是: [Giraffe, Lemur]

4、Distinct元素去重

咱們還可使用distinct方法對管道中的元素去重,涉及到去重就必定涉及到元素之間的比較,distinct方法時調用Object的equals方法進行對象的比較的,若是你有本身的比較規則,能夠重寫equals方法。spring

List<String> uniqueAnimals = Stream.of("Monkey", "Lion", "Giraffe", "Lemur", "Lion")
        .distinct()
        .collect(Collectors.toList());

上面代碼去重以後的結果是: ["Monkey", "Lion", "Giraffe", "Lemur"]vuex

5、Sorted排序

默認的狀況下,sorted是按照字母的天然順序進行排序。以下代碼的排序結果是:[Giraffe, Lemur, Lion, Monkey],字數按順序G在L前面,L在M前面。第一位沒法區分順序,就比較第二位字母。編程

List<String> alphabeticOrder = Stream.of("Monkey", "Lion", "Giraffe", "Lemur")
        .sorted()
        .collect(Collectors.toList());

排序咱們後面還會給你們詳細的講一講,因此這裏暫時只作一個瞭解。後端

6、串行、並行與順序

一般狀況下,有狀態和無狀態操做不須要咱們去關心。除非?:你使用了並行操做。數組

仍是用班級按身高排隊爲例:班級有一我的負責排序,這個排序結果最後就會是正確的。那若是有2個、3我的負責按大小個排隊呢?最後可能就亂套了。一我的只能保證本身排序的人的順序,他沒法保證其餘人的排隊順序。

  • 串行的好處是能夠保證順序,可是一般狀況下處理速度慢一些
  • 並行的好處是對於元素的處理速度快一些(一般狀況下),可是順序沒法保證。這可能會致使進行一些有狀態操做的時候,最後獲得的不是你想要的結果。

Stream.of("Monkey", "Lion", "Giraffe", "Lemur", "Lion")
        .parallel()
        .forEach(System.out::println);
  • parallel()函數表示對管道中的元素進行並行處理,而不是串行處理。可是這樣就有可能致使管道流中後面的元素先處理,前面的元素後處理,也就是元素的順序沒法保證。
若是數據量比較小的狀況下,不太能觀察到,數據量大的話,就能觀察到數據順序是沒法保證的。
Monkey
Lion
Lemur
Giraffe
Lion

一般狀況下,parallel()可以很好的利用CPU的多核處理器,達到更好的執行效率和性能,建議使用。可是有些特殊的狀況下,parallel並不適合:深刻了解請看這篇文章:
https://blog.oio.de/2016/01/22/parallel-stream-processing-in-java-8-performance-of-sequential-vs-parallel-stream-processing/
該文章中幾個觀點,說明並行操做的適用場景:

  • 數據源易拆分:從處理性能的角度,parallel()更適合處理ArrayList,而不是LinkedList。由於ArrayList從數據結構上講是基於數組的,能夠根據索引很容易的拆分爲多個。

  • 適用於無狀態操做:每一個元素的計算都不得依賴或影響任何其餘元素的計算,的運算場景。
  • 基礎數據源無變化:從文本文件裏面邊讀邊處理的場景,不適合parallel()並行處理。parallel()一開始就容量固定的集合,這樣可以平均的拆分、同步處理。

歡迎關注個人博客,裏面有不少精品合集

  • 本文轉載註明出處(必須帶鏈接,不能只轉文字):字母哥博客

以爲對您有幫助的話,幫我點贊、分享!您的支持是我不竭的創做動力! 。另外,筆者最近一段時間輸出了以下的精品內容,期待您的關注。

相關文章
相關標籤/搜索