java8-Stream-構建流

stream 基礎定義

  • 元素序列——就像集合一樣,流也提供了一個接口谣拣,可以訪問特定元素類型的一組有序 值碑韵。因為集合是數據結構,所以它的主要目的是以特定的時間/空間復雜度存儲和訪問元 素(如ArrayList 與 LinkedList)蕊连。但流的目的在于表達計算悬垃,比如你前面見到的 filter、sorted和map甘苍。集合講的是數據尝蠕,流講的是計算。
  • 源——流會使用一個提供數據的源载庭,如集合看彼、數組或輸入/輸出資源。
  • 數據處理操作——流的數據處理功能支持類似于數據庫的操作昧捷,以及函數式編程語言中 的常用操作闲昭,如filter、map靡挥、reduce序矩、find、match跋破、sort等簸淀。流操作可以順序執(zhí) 行,也可并行執(zhí)行毒返。
    此外租幕,流操作有兩個重要的特點。
  • 流水線——很多流操作本身會返回一個流拧簸,這樣多個操作就可以鏈接起來劲绪,形成一個大
    的流水線。這讓我們下一章中的一些優(yōu)化成為可能盆赤,如延遲和短路贾富。流水線的操作可以看作對數據源進行數據庫式查詢。
  • 內部迭代——與使用迭代器顯式迭代的集合不同牺六,流的迭代操作是在背后進行的颤枪。

構建流

所有的流構建方法 最終都會調用如下的這個方法

/* 
 * @param spliterator a {@code Spliterator} describing the stream elements
 * @param parallel if {@code true} then the returned stream is a parallel stream; 
 *                 if {@code false} the returned stream is a sequential stream.
 */        
public static <T> Stream<T> stream(Spliterator<T> spliterator, boolean parallel) {
        Objects.requireNonNull(spliterator);
        return new ReferencePipeline.Head<>(spliterator,
                                            StreamOpFlag.fromCharacteristics(spliterator),
                                            parallel);
}
  • 由值創(chuàng)建流
    Stream 提供兩個靜態(tài)方法可以把值轉換成流
方法一:
List<Integer> list = Arrays.asList(1, 2, 3);
Stream<List<Integer>> stream = Stream.of(list);

方法二:
Stream<Object> stream1 = Stream.of(1, 2, "3");

注:這兩種方法返回類型 是編譯器通過類型推斷得出的。
使用方法二淑际,源碼中有這么一行提示:Creating a stream from an array is safe
  • 由數組創(chuàng)建流
List<Integer> list = Arrays.asList(1, 2, 3);
Stream<Integer> stream = list.stream();
  • 由函數生成:創(chuàng)建無限流
方法一:迭代
Stream<Integer> stream = Stream.iterate(0, n -> n + 2);

該迭代的源碼如下:
public static<T> Stream<T> iterate(final T seed, final UnaryOperator<T> f) {
        Objects.requireNonNull(f);
        final Iterator<T> iterator = new Iterator<T>() {
            @SuppressWarnings("unchecked")
            T t = (T) Streams.NONE;

            @Override
            public boolean hasNext() {
                return true;
            }

            @Override
            public T next() {
                return t = (t == Streams.NONE) ? seed : f.apply(t);
            }
        };
        return StreamSupport.stream(Spliterators.spliteratorUnknownSize(
                iterator,
                Spliterator.ORDERED | Spliterator.IMMUTABLE), false);
}

如上所示畏纲,第二個參數為一個 lambda UnaryOperator<T>  
關于這個指令的 解釋是:傳入一個 參數T扇住,返回一個參數T,如 (n -> n+2)盗胀;傳入 一個 (int n)艘蹋,返回一個 (int + 2) 類型相同,
因此票灰,我們有的迭代方式也可以

Stream.iterate(new int[]{0, 1},t -> new int[]{t[1], t[0]+t[1]})
方法二:生成
Stream.generate(Math::random)

迭代生成源碼如下:
public static<T> Stream<T> generate(Supplier<T> s) {
        Objects.requireNonNull(s);
        return StreamSupport.stream(
                new StreamSpliterators.InfiniteSupplyingSpliterator.OfRef<>(Long.MAX_VALUE, s), false);
}
如上所示簿训,此函數只會接受一個 lambda supplier<T> 作為一個生產者,
由于該生產者可能會在類內部存儲某些狀態(tài)米间,但是這些狀態(tài)有可能是可變的,如果在并行流中使用可能不會得到我們的期望值膘侮。
 Stream.generate(new Supplier<Object>() {
    long sum = 0;
    @Override
    public Object get() {
        return sum += 1;
    }
  });
這段代碼如果在并行流中使用屈糊,由于sum 會被所有線程共用,所以這種寫法是錯誤的琼了。

迭代 iterate 在迭代的方法中由于每次迭代都是靜態(tài)的 所以下面的這種寫法是正確的:
Stream.iterate(0, new UnaryOperator<Integer>() {
   int sum = 1;
   @Override
   public Integer apply(Integer integer) {
       return sum += integer;  
   }
}).limit(5).parallel().forEach(System.out::println);

但是由于并行流的順序不確定性逻锐,所以我們的期望值:0,1雕薪,2昧诱,4,8 可能和我們運行的結果(某次運行結果:2所袁,8盏档,4,1燥爷,0)并不一致蜈亩。
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市前翎,隨后出現的幾起案子稚配,更是在濱河造成了極大的恐慌,老刑警劉巖港华,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件道川,死亡現場離奇詭異,居然都是意外死亡立宜,警方通過查閱死者的電腦和手機冒萄,發(fā)現死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來赘理,“玉大人宦言,你說我怎么就攤上這事∩棠#” “怎么了奠旺?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵蜘澜,是天一觀的道長。 經常有香客問我响疚,道長鄙信,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任忿晕,我火速辦了婚禮装诡,結果婚禮上,老公的妹妹穿的比我還像新娘践盼。我一直安慰自己鸦采,他們只是感情好,可當我...
    茶點故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布咕幻。 她就那樣靜靜地躺著渔伯,像睡著了一般。 火紅的嫁衣襯著肌膚如雪肄程。 梳的紋絲不亂的頭發(fā)上锣吼,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天,我揣著相機與錄音蓝厌,去河邊找鬼玄叠。 笑死,一個胖子當著我的面吹牛拓提,可吹牛的內容都是我干的读恃。 我是一名探鬼主播,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼崎苗,長吁一口氣:“原來是場噩夢啊……” “哼狐粱!你這毒婦竟也來了?” 一聲冷哼從身側響起胆数,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤肌蜻,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后必尼,有當地人在樹林里發(fā)現了一具尸體蒋搜,經...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年判莉,在試婚紗的時候發(fā)現自己被綠了豆挽。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,785評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡券盅,死狀恐怖帮哈,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情锰镀,我是刑警寧澤娘侍,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布咖刃,位于F島的核電站,受9級特大地震影響憾筏,放射性物質發(fā)生泄漏嚎杨。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一氧腰、第九天 我趴在偏房一處隱蔽的房頂上張望枫浙。 院中可真熱鬧,春花似錦古拴、人聲如沸箩帚。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽膏潮。三九已至,卻和暖如春满力,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背轻纪。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工油额, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人刻帚。 一個月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓潦嘶,卻偏偏與公主長得像,于是被迫代替她去往敵國和親崇众。 傳聞我的和親對象是個殘疾皇子掂僵,可洞房花燭夜當晚...
    茶點故事閱讀 44,713評論 2 354

推薦閱讀更多精彩內容

  • Spring Cloud為開發(fā)人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發(fā)現顷歌,斷路器锰蓬,智...
    卡卡羅2017閱讀 134,654評論 18 139
  • ??集合是Java中使用最多的API。要是沒有集合眯漩,還能做什么呢芹扭?幾乎每個java應用程序都會制造處理集合。集合對...
    瓊珶和予閱讀 478評論 0 0
  • 關于 本文是對 Brian Goetz的State of the Lambda: Libraries Editio...
    aaron688閱讀 1,342評論 0 5
  • Java8 in action 沒有共享的可變數據,將方法和函數即代碼傳遞給其他方法的能力就是我們平常所說的函數式...
    鐵牛很鐵閱讀 1,229評論 1 2
  • 第一章 為什么要關心Java 8 使用Stream庫來選擇最佳低級執(zhí)行機制可以避免使用Synchronized(同...
    謝隨安閱讀 1,491評論 0 4