国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

使用流

codercao / 2897人閱讀

摘要:將在非空的時候返回值,否則會拋出沒有這個元素的異常。構建流現(xiàn)在我們已經(jīng)能夠使用從集合生成流了。由文件生成流不重復的單詞數(shù)預處理獲取流,使用后不用手動關閉流。我們使用得到流,其中每個元素就是文本里的一行。

篩選和切片 filter

filter 會接受一個謂詞作為參數(shù),并返回符合該條件的元素流。

        List vegetarianMenu = menu
                .stream()
                .filter(Dish::getVegetarian)
                .collect(Collectors.toList());

會篩選出素食的菜肴。

distinct

distinct 會返回一個元素各異的流,也就是去重。

        List caloriesMenu = menu
                .stream()
                .filter((Dish dish) -> 350 == dish.getCalories())
                .map(Dish::getCalories)
                .distinct()
                .collect(Collectors.toList());

會篩選出卡路里為350的菜肴并去重(米飯和對蝦二選一)。

limit(n)

limit(n) 會返回一個不超過給定長度的流。

        List caloriesMenu = menu
                .stream()
                .filter((Dish dish) -> 350 < dish.getCalories())
                .limit(3)
                .collect(Collectors.toList());

List 是有序集合所以會順序篩選出三個,而如果是 Set 無序的則不會以任何順序排列。

skip(n)

skip(n) 返回一個人掉了前 n 個元素的流,和 limit(n) 是互補的。

        List caloriesMenu = menu
                .stream()
                .filter((Dish dish) -> 350 < dish.getCalories())
                .skip(3)
                .collect(Collectors.toList());
映射

map 返回一個映射好的元素流。如果我們要找出每個菜肴的名稱有多長,那么可以這樣思考:第一,我們需要知道菜肴的名稱。第二,計算菜肴名稱的長度。

        List caloriesMenu = menu
                .stream()
                // 映射名稱字符串
                .map(Dish::getName)
                // 映射字符串長度
                .map(String::length)
                .collect(Collectors.toList());
流的扁平化

返回菜肴名稱的長度已經(jīng)做到了,如果有奇怪的需求,比如將菜肴名稱打碎成字符并去重……

        List caloriesMenu = menu
                .stream()
                // 映射名稱字符串
                .map(Dish::getName)
                // 將字符串分割為字符數(shù)組 String[]
                .map((String string) -> string.split(""))
                // Arrays.stream() 可以接收一個數(shù)組并產(chǎn)生一個流,再調(diào)用 flatMap 將其轉成單個流
                .flatMap(Arrays::stream)
                // 去重
                .distinct()
                // 保存
                .collect(Collectors.toList());

扁平化在這里就是讓字符數(shù)組不是分別映射成一個流,而是映射成流的內(nèi)容,然后將使用 Arrays::stream 時生成的單個流都被合并起來。

查找和匹配 anyMatch

anyMatch 可以檢查謂詞是否至少匹配一個元素。

        // 檢查是否至少含有一道是素食的菜肴
        Boolean b = menu
                .stream()
                .anyMatch(Dish::getVegetarian);
allMatch

allMatch 可以檢查謂詞是否全部匹配。

        // 檢查是否全部是素食
        Boolean b = menu
                .stream()
                .anyMatch(Dish::getVegetarian);
noneMatch

noneMatch 可以檢查謂詞是否全部不匹配。

        // 檢查是否全部不是素食
        Boolean b = menu
                .stream()
                .noneMatch(Dish::getVegetarian);

以上這三種操作都用到了所謂的短路,也和 Java 中!、&&和||運算符意義一樣。

findAny

findAny 將返回當前流中的任意元素。

        Optional dishOptional = menu
                .stream()
                .findAny();

Optional 是一個容器類,代表一個值存在或不存在。有可能 findAny 什么也沒找到,所以如果用 Dish 對象直接裝可能會報空指針錯誤。本章不會深入了解 Optional,但可以先簡單介紹一下這個類的一些有用的方法。

isPresent() 將在非空的時候返回 true。

ifPresent(Consumer consumer) 將在非空的時候執(zhí)行 Consumer 的代碼,再第二章的時候我們知道 Consumer 可以接受一個對象并進行操作。

T get() 將在非空的時候返回值,否則會拋出沒有這個元素的異常。

T orElse(T other) 將在非空的時候返回值,否則返回一個默認值。

比如上面的代碼可以變成這樣

        menu.stream().findAny().ifPresent(System.out::println);

就可以打印輸出任意菜肴的信息。

findFirst

findAny 類似,只不過返回有序集合的第一個元素。

        Optional dishOptional = menu
                .stream()
                .findFirst();

那么 findAnyfindFirst 有什么區(qū)別呢?在并行計算里面,找到第一個元素會需要很多思考,所以一般在并行處理時用 findAny

歸納

reduce 操作可以吧一個流中的元素組合起來,比如菜單里的總卡路里。此類查詢需要將流中所有元素反復結合起來,得到一個值。這樣的查詢操作可以被歸類為 歸約 操作,用函數(shù)式編程語言的術語來說,這稱為 折疊

元素求和

平常使用 for-each 來處理總卡路里我們一般會這樣做

        Integer integer = 0;
        for (Dish dish : menu) {
            integer += dish.getCalories();
        }

在流中可以使用 reduce 方法來處理

        Integer integer = menu
                .stream()
                .map(Dish::getCalories)
                .reduce(0, (Integer a, Integer b) -> a + b);

好像有點復雜,沒關系,接下來可以詳細講解。

首先我們用 map 將 Dish 對象映射成其卡路里值的 Integer 類型。然后調(diào)用 reduce 將每個映射好的 Integer 組合(相加)。其中 reduce 方法第一個參數(shù)代表初始值,后面跟著一個 BinaryOperator 的函數(shù)式接口。這個函數(shù)式接口目的就是將兩個元素組合。

可以看一下 BinaryOperator 的源碼

@FunctionalInterface
public interface BinaryOperator extends BiFunction {
    public static  BinaryOperator minBy(Comparator comparator) {
        Objects.requireNonNull(comparator);
        return (a, b) -> comparator.compare(a, b) <= 0 ? a : b;
    }

    public static  BinaryOperator maxBy(Comparator comparator) {
        Objects.requireNonNull(comparator);
        return (a, b) -> comparator.compare(a, b) >= 0 ? a : b;
    }
}

實際上我們調(diào)用的是第三章有提到過的 BiFunction 里的 apply 方法

@FunctionalInterface
public interface BiFunction {
    R apply(T t, U u);
}

BinaryOperator 它接受兩個同類型參數(shù)并返回一個同類型的對象。

所以我們可以這樣來寫

        BinaryOperator integerBinaryOperator = (Integer a, Integer b) -> a + b;

代表計算 a + b。而 reduce 自帶循環(huán),所以會在背后進行類似于 a += b 一樣的邏輯操作。reduce還有一個重載的版本,可以不接受初始值返回一個 Optional 對象。

        Optional integer = menu
                .stream()
                .map(Dish::getCalories)
                .reduce((Integer a, Integer b) -> a + b);

用 Optional 的意義與之前一樣,考慮到了集合為空的情況。

最大和最小

reduce 同樣可以用來做大小比較,因為其需要的 BinaryOperator 自帶有比較方法。

最大

        Optional integer = menu
                .stream()
                .map(Dish::getCalories)
                .reduce(Integer::max);

其中 reduce(Integer::max) 是

        reduce((Integer integer1, Integer integer2) -> Integer.max(integer1, integer2))

的縮寫。計算最小值只需要將 max 換成 min 就行。歸納方法的對比傳統(tǒng)的 for-each 優(yōu)勢是可以把內(nèi)部迭代抽象化,這讓其內(nèi)部可以并行化而不用我們自己去實現(xiàn)并行處理。

但是這種并行是有限制的,不是將所有的 stream 換成 parallelStream 就行了。

像 map 或 filter 等操作會從輸入流中獲取每一個元素并在輸出流中得到至多一個結果。這些操作一般是無狀態(tài)的,做并行是可行的。

像 reduce、max 等操作需要內(nèi)部狀態(tài)來累積結果,因為求和肯定是需要之前數(shù)的和加上現(xiàn)在選擇的這個元素,但無論哪個都是有限的,所以稱為有界,是可以直接做并行。

相反,如同 distinct 操作,是需要接受一個流再生成一個流,并且去重操作是需要知道先前的歷史流是什么樣的,例如把所有質數(shù)倒序,就需要最大的那個質數(shù),但這是不存在的,所以稱為無界狀態(tài)。做并行需要好生思考一番。

關于去重,其實可以換一種思路,將有序集合(List)轉為無序集合(Set)就自動去重了。

        Set caloriesMenu = menu
                .stream()
                .filter((Dish dish) -> 350 == dish.getCalories())
                .map(Dish::getCalories)
                .collect(Collectors.toSet());
數(shù)值范圍

在和數(shù)字打交道時,比較常用的就是在一個數(shù)值范圍內(nèi)生成數(shù)字。Java 8引入了兩個可以用于 IntStream 和 LongStream 的靜態(tài)方法,幫助生成范圍:range 和 rangeClosed。是不包含結束值的,比如傳入(0,100)就會運算到99結束。

比如我們需要統(tǒng)計0~100里偶數(shù)的個數(shù)(包含100)

        long l = IntStream
                .rangeClosed(0, 100)
                .filter((int n) -> n % 2 == 0)
                .count();

這樣就統(tǒng)計出了51個偶數(shù)個數(shù),如果不包含100就用 range,會統(tǒng)計50個。

構建流

現(xiàn)在我們已經(jīng)能夠使用 Stream 從集合生成流了。那么如何從值序列、數(shù)組和文件生成流,甚至函數(shù)來創(chuàng)建無限流?

創(chuàng)建一個空流
        Stream stringStream = Stream.empty();
由值創(chuàng)建流
        Stream stringStream = Stream.of("qwe", "asd", "zxc");
        stringStream.map(String::toUpperCase).forEach(System.out::println);

這樣會把小寫字符串全部轉成大寫。

由數(shù)組創(chuàng)建流
        int[] ints = {1, 2, 3, 4, 5};
        int sum = Arrays.stream(ints).sum();

這樣會把所有的數(shù)字相加。

由文件生成流
        /*
        /Users/cciradih/java:
        
        Java Platform, Standard Edition (Java SE) lets you develop and deploy Java applications on desktops and servers,
        as well as in today"s demanding embedded environments. Java offers the rich user interface, performance,
        versatility, portability, and security that today"s applications require.
         */


        // 不重復的單詞數(shù)
        long uniqueWords = 0;
        // 預處理獲取流,使用后不用手動關閉流。
        try (Stream stringStream = Files.lines(Paths.get("/Users/cciradih/java"), Charset.defaultCharset())) {
            // 從流中統(tǒng)計
            uniqueWords = stringStream
                    // 扁平化字符串數(shù)組
                    .flatMap((String line) -> Arrays.stream(line.split(" ")))
                    // 去重
                    .distinct()
                    // 統(tǒng)計
                    .count();
        } catch (IOException e) {
            e.printStackTrace();
        }

這里是用到了新的 NIO,以便利用 Stream。我們使用 Files.lines 得到流,其中每個元素就是文本里的一行。然后使用 split 拆分成單詞,并用 flatMap 將其扁平化。最后用 distinct 去重再用 count 統(tǒng)計。

由函數(shù)生成流

Stream 提供了兩個靜態(tài)方法來從函數(shù)生成流 iterate 和 gengrate。這兩個操作都可以創(chuàng)建無線流。

iterate

        Stream.iterate(0, (Integer integer) -> integer + 2);

這會創(chuàng)建一個從0開始無限的偶數(shù)流。

gengrate

        Stream.generate(Math::random);

這會創(chuàng)建一個0到1之間無限的隨機數(shù)。

這一章詳細講了流的使用場景和需要注意的地方,特別是和傳統(tǒng)的操作做對比,能更好地支持并行處理。

Java 8 實戰(zhàn) 第五章 使用流 讀書筆記

歡迎加入咖啡館的春天(338147322)。

文章版權歸作者所有,未經(jīng)允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/70209.html

相關文章

  • 第十五章 輸入輸出系統(tǒng)

    摘要:在包下主要包括輸入輸出兩種流,每種輸入輸出流又可分為字節(jié)流和字符流兩大類。輸入輸出是從程序運行所在的內(nèi)存的角度而言的。的輸入流主要由和作為基類,而輸出流主要由和作為基類。 本章主要參考和摘自瘋狂java講義上面的(java編程思想的后面看過后有新的內(nèi)容再補充進去吧)。  輸入輸出是所有程序都必需的部分————使用輸入機制允許程序讀取外部數(shù)據(jù)(包括磁盤、光盤等存儲設備上的數(shù)據(jù)和用戶輸入的...

    hankkin 評論0 收藏0
  • 高薪程序員&amp;面試題精講系列22之說說Java的IO,常用哪些IO

    摘要:一面試題及剖析今日面試題今天壹哥帶各位復習一塊可能會令初學者比較頭疼的內(nèi)容,起碼當時讓我很有些頭疼的內(nèi)容,那就是流。在這里壹哥會從兩部分展開介紹流,即與流。除此之外盡量使用字節(jié)流。關閉此輸入流并釋放與流相關聯(lián)的任何系統(tǒng)資源。 一. 面試題及剖析 1. 今日面試題 今天 壹哥 帶各位復習一塊可...

    fnngj 評論0 收藏0
  • Java IO

    摘要:分類一按操作方式類結構字節(jié)流和字符流字節(jié)流以字節(jié)為單位,每次次讀入或讀出是位數(shù)據(jù)。該對象并不是流體系中的一員,其封裝了字節(jié)流,同時還封裝了一個緩沖區(qū)字符數(shù)組,通過內(nèi)部的指針來操作字符數(shù)組中的數(shù)據(jù)。 分類一:按操作方式(類結構) 字節(jié)流和字符流: 字節(jié)流:以字節(jié)為單位,每次次讀入或讀出是8位數(shù)據(jù)。可以讀任何類型數(shù)據(jù)。 字符流:以字符為單位,每次次讀入或讀出是16位數(shù)據(jù)。其只能讀取字符類...

    Salamander 評論0 收藏0
  • 第十一章-IO#yyds干貨盤點#

    摘要:是一個系統(tǒng)支持的所有字符的集合,包括各國家文字標點符號圖形符號數(shù)字等字符集簡體中文碼表。支持中國國內(nèi)少數(shù)民族的文字,同時支持繁體漢字以及日韓漢字等字符集為表達任意語言的任意字符而設計,是業(yè)界的一種標準,也稱為統(tǒng)一碼標準萬國碼。 1 File1.1 File類的概述和構造方法File: 它是文件和目錄路徑名的抽象...

    不知名網(wǎng)友 評論0 收藏0
  • Java 輸入/輸出 I/O RandomAccessFile

    摘要:當使用節(jié)點流進行輸入輸出時,程序直接連接到實際的數(shù)據(jù)源,和時間的輸入輸出節(jié)點連接處理流則用于對一個已存在的流進行連接或封裝,通過封裝后的流來實現(xiàn)數(shù)據(jù)讀寫功能,處理流也被稱為高級流。 文件的編碼 文本文件就是字節(jié)序列,可以是任意編碼形式。在中文操作系統(tǒng)上直接創(chuàng)建文本文件,則該文本文件只能識別ANSI編碼,其他編碼方式會產(chǎn)生亂碼 package imooc.io; import java...

    Eirunye 評論0 收藏0
  • Java IO (一),理解

    摘要:的是實現(xiàn)輸入輸出的基礎中把不同的輸入輸出源鍵盤文件網(wǎng)絡連接抽象的表述為流流的分類輸入流和輸出流按照流的流向來分輸入流只能從中讀數(shù)據(jù)而不能向其中寫數(shù)據(jù)輸出流只能向其中寫出數(shù)據(jù)而不能從中讀取數(shù)據(jù)此處的輸入輸出涉及到一個方向問題數(shù)據(jù)從內(nèi)存到硬盤被 Java的IO是實現(xiàn)輸入輸出的基礎,Java中把不同的輸入/輸出源(鍵盤,文件,網(wǎng)絡連接)抽象的表述為流,stream. 流的分類 輸入流和輸...

    羅志環(huán) 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<