成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

《Java8實(shí)戰(zhàn)》-第四章讀書(shū)筆記(引入流Stream)

_ivan / 2989人閱讀

摘要:內(nèi)部迭代與使用迭代器顯式迭代的集合不同,流的迭代操作是在背后進(jìn)行的。流只能遍歷一次請(qǐng)注意,和迭代器類似,流只能遍歷一次。

流(Stream) 流是什么

流是Java API的新成員,它允許你以聲明性方式處理數(shù)據(jù)集合(通過(guò)查詢語(yǔ)句來(lái)表達(dá),而不是臨時(shí)編寫(xiě)一個(gè)實(shí)現(xiàn))。就現(xiàn)在來(lái)說(shuō),你可以把它們看成遍歷數(shù)據(jù)集的高級(jí)迭代器。此外,流還可以透明地并行處理,你無(wú)需寫(xiě)任何多線程代碼了!我會(huì)在后面的筆記中詳細(xì)記錄和解釋流和并行化是怎么工作的。我們簡(jiǎn)單看看使用流的好處吧。下面兩段代碼都是用來(lái)返回低熱量的菜肴名稱的,并按照卡路里排序,一個(gè)是用Java7寫(xiě)的,另一個(gè)是用Java8的流寫(xiě)的。比較一下。不用太擔(dān)心Java 8代碼怎么寫(xiě),我們?cè)诮酉聛?lái)會(huì)對(duì)它進(jìn)行詳細(xì)的了解。

菜單篩選

使用Java7:

private static List getLowCaloricDishesNamesInJava7(List dishes) {
    List lowCaloricDishes = new ArrayList<>();
    // 遍歷篩選出低于400卡路里的菜,添加到另外一個(gè)集合中
    for (Dish d : dishes) {
        if (d.getCalories() < 400) {
            lowCaloricDishes.add(d);
        }
    }

    // 對(duì)集合按照卡路里大小進(jìn)行排序
    List lowCaloricDishesName = new ArrayList<>();
    Collections.sort(lowCaloricDishes, new Comparator() {
        @Override
        public int compare(Dish d1, Dish d2) {
            return Integer.compare(d1.getCalories(), d2.getCalories());
        }
    });

    // 遍歷將菜名添加到另外一個(gè)集合中
    for (Dish d : lowCaloricDishes) {
        lowCaloricDishesName.add(d.getName());
    }
    return lowCaloricDishesName;
}

在上面的代碼中,看起來(lái)很冗長(zhǎng),我們使用了一個(gè)“垃圾變量”lowCaloricDishes。它唯一的作用就是作為一次性的中間容器。 在Java8,實(shí)現(xiàn)的細(xì)節(jié)被放到了它本該歸屬的庫(kù)力了。
使用Java8:

private static List getLowCaloricDishesNamesInJava8(List dishes) {
    return dishes.stream()
            // 選出400卡路里以下的菜肴
            .filter(d -> d.getCalories() < 400)
            // 按照卡路里排序
            .sorted(comparing(Dish::getCalories))
            // 提取菜名
            .map(Dish::getName)
            // 轉(zhuǎn)為集合
            .collect(toList());
}

太酷了!原本十幾行的代碼,現(xiàn)在只需要一行就可以搞定,這樣的感覺(jué)真的是太棒了!還有一個(gè)很棒的新特性,為了利用多核架構(gòu)并行執(zhí)行代碼,我們只需要將stream()改為parallelStream()即可:

private static List getLowCaloricDishesNamesInJava8(List dishes) {
    return dishes
            .parallelStream()
            // 選出400卡路里以下的菜肴
            .filter(d -> d.getCalories() < 400)
            // 按照卡路里排序
            .sorted(comparing(Dish::getCalories))
            // 提取菜名
            .map(Dish::getName)
            // 轉(zhuǎn)為集合
            .collect(toList());
}

你可能會(huì)想,在調(diào)用parallelStream方法時(shí)到底發(fā)生了什么。用了多少個(gè)線程?對(duì)性能有多大的提升?不用著急,在后面的讀書(shū)筆記中會(huì)討論這些問(wèn)題?,F(xiàn)在,你可以看出,從軟件工程師的角度來(lái)看,新的方法有幾個(gè)顯而易見(jiàn)的好處。

代碼是以聲明性的方式寫(xiě)的:說(shuō)明想要完成什么(篩選熱量低的菜肴)而不是說(shuō)明如何實(shí)現(xiàn)一個(gè)操作(利用循環(huán)和if條件等控制流語(yǔ)句)。

你可以把幾個(gè)基礎(chǔ)操作鏈接起來(lái),來(lái)表達(dá)復(fù)雜的數(shù)據(jù)處理流水線(在 filter 后面接上

sorted 、 map 和 collect 操作),同時(shí)保持代碼清晰可讀。 filter 的結(jié)果被傳給了 sorted 方法,再傳給 map 方法,最后傳給 collect 方法。

filter、sorted、map和collect等操作是與具體線程模型無(wú)關(guān)的高層次構(gòu)件,所以它們的內(nèi)部實(shí)現(xiàn)可以是單線程的,也可能透明地充分利用你的多核架構(gòu)!在實(shí)踐中,這意味著我們用不著為了讓某些數(shù)據(jù)處理任務(wù)并行而去操心線程和鎖了,Stream API都替你做好了!

現(xiàn)在就來(lái)仔細(xì)探討一下怎么使用Stream API。我們會(huì)用流與集合做類比,做點(diǎn)兒鋪墊。下一
章會(huì)詳細(xì)討論可以用來(lái)表達(dá)復(fù)雜數(shù)據(jù)處理查詢的流操作。我們會(huì)談到很多模式,如篩選、切片、
查找、匹配、映射和歸約,還會(huì)提供很多測(cè)驗(yàn)和練習(xí)來(lái)加深你的理解。接下來(lái),我們會(huì)討論如何創(chuàng)建和操縱數(shù)字流,比如生成一個(gè)偶數(shù)流,或是勾股數(shù)流。最后,我們會(huì)討論如何從不同的源(比如文件)創(chuàng)建流。還會(huì)討論如何生成一個(gè)具有無(wú)窮多元素的流,這用集合肯定是搞不定。

流簡(jiǎn)介

要討論流,我們首先來(lái)談?wù)劶?,這是最容易上手的方式了。Java8中的集合支持一個(gè)新的stream方法,它會(huì)返回一個(gè)流(接口定義在 java.util.stream.Stream 里)。你在后面會(huì)看到,還有很多其他的方法可以得到流,比如利用數(shù)值范圍或從I/O資源生成流元素。

那么,流到底是什么呢?簡(jiǎn)短的定義就是“從支持?jǐn)?shù)據(jù)處理操作的源生成的元素序列”。讓我們一步步剖析這個(gè)定義。

元素序列:就像集合一樣,流也提供了一個(gè)接口,可以訪問(wèn)特定元素類型的一組有序值。因?yàn)榧鲜菙?shù)據(jù)結(jié)構(gòu),所以它的主要目的是以特定的時(shí)間/空間復(fù)雜度存儲(chǔ)和訪問(wèn)元素(如ArrayList 與 LinkedList )。但流的目的在于表達(dá)計(jì)算,比如你前面見(jiàn)到的filter 、 sorted 和 map 。集合講的是數(shù)據(jù),流講的是計(jì)算。

源:流會(huì)使用一個(gè)提供數(shù)據(jù)的源,如集合、數(shù)組或輸入/輸出資源。請(qǐng)注意,從有序集合生成流時(shí)會(huì)保留原有的順序。由列表生成的流,其元素順序與列表一致。

數(shù)據(jù)處理操作:流的數(shù)據(jù)處理功能支持類似于數(shù)據(jù)庫(kù)的操作,以及函數(shù)式編程語(yǔ)言中的常用操作,如filter、map、reduce、find、match、sort等。流操作可以順序執(zhí)行,也可并行執(zhí)行。

此外,流操作有兩個(gè)重要的特點(diǎn)。

流水線:很多流操作本身會(huì)返回一個(gè)流,這樣多個(gè)操作就可以鏈接起來(lái),形成一個(gè)大的流水線。

內(nèi)部迭代:與使用迭代器顯式迭代的集合不同,流的迭代操作是在背后進(jìn)行的。

讓我們來(lái)看一段能夠體現(xiàn)所有這些概念的代碼:

List menu = Dish.MENU;
// 從menu獲得流
List threeHighCaloricDishNames = menu.stream()
        // 通過(guò)鏈?zhǔn)讲僮?,篩選出高熱量的菜肴
        .filter(d -> d.getCalories() > 300)
        // 獲取菜名
        .map(Dish::getName)
        .limit(3)
        .collect(Collectors.toList());
// [pork, beef, chicken]
System.out.println(threeHighCaloricDishNames);

看起來(lái)很簡(jiǎn)單,就算不明白也沒(méi)關(guān)系,我們來(lái)了解了解,剛剛使用到的一些方法:

filter: 接受Lambda,從流中排除某些元素。在剛剛的代碼中,通過(guò)傳遞Lambda表達(dá)式 d -> d.getCalories() > 300,選擇出熱量高于300卡路里的菜肴。

map:接受一個(gè)Lambda,將元素轉(zhuǎn)換成其他形式或提取信息。在剛剛的代碼中,通過(guò)傳遞方法引用Dish::getName,提取了每道菜的菜名。

limit:截?cái)嗔?,使其元素不超過(guò)給定的數(shù)量。

collect:將流轉(zhuǎn)換為其他形式。在剛剛的代碼中,流被轉(zhuǎn)為一個(gè)List集合。

在剛剛解釋的這段代碼,與遍歷處理菜單集合的代碼有很大的不同。首先,我們使用了聲明性的方式來(lái)處理菜單數(shù)據(jù)。我們并沒(méi)有去實(shí)現(xiàn)篩選(filter)、提?。╩ap)或截?cái)啵╨imit)功能,Stream庫(kù)已經(jīng)自帶了。因此,StreamAPI在決定如何優(yōu)化這條流水線時(shí)更為靈活。例如,篩選、提取和截?cái)嗖僮骺梢砸淮芜M(jìn)行,并在找到這三道菜后立即停止。

流與集合

Java現(xiàn)有的集合概念和新的流概念都提供了接口,來(lái)配合代表元素型有序值的數(shù)據(jù)接口。所謂有序,就是說(shuō)我們一般是按順序取用值,而不是隨機(jī)取用的。那這兩者有什么區(qū)別呢?

打個(gè)比方說(shuō),我們?cè)诳措娪暗臅r(shí)候,這些視頻就是一個(gè)流(字節(jié)流或幀流),流媒體視頻播放器只要提前下載用戶觀看位置的那幾幀就可以了,這樣不用等到流中大部分值計(jì)算出來(lái)。比如,我們?cè)赮outube上看的視頻進(jìn)度條隨便拖動(dòng)到一個(gè)位置,你會(huì)發(fā)現(xiàn)它很快就開(kāi)始播放了,不需要將整個(gè)視頻都加載好,而是加載了一段。如果,不按照這種方式的話,我們可以想象一下,視頻播放器可能沒(méi)有將整個(gè)流作為集合,保存所需要的內(nèi)存緩沖區(qū)——而且要是非得等到最后一幀出現(xiàn)才能開(kāi)始看,那等待的時(shí)間就太長(zhǎng)了,早就沒(méi)耐心看了。

初略地說(shuō),集合與流之間的差異就在于什么時(shí)候進(jìn)行計(jì)算。集合是一個(gè)內(nèi)存中的數(shù)據(jù)結(jié)構(gòu),它包含數(shù)據(jù)結(jié)構(gòu)中目前所有的值,集合中的每個(gè)元素都得先算出來(lái)才能添加到集合中。

相比之下,流則是在概念上固定的數(shù)據(jù)結(jié)構(gòu),其元素則是按需計(jì)(懶加載)算的。需要多少就給多少。這是一種生產(chǎn)者與消費(fèi)者的關(guān)系。從另一個(gè)角度來(lái)說(shuō),流就像是一個(gè)延遲創(chuàng)建的集合:只有在消費(fèi)者要求的時(shí)候才會(huì)生成值。與之相反,集合則是急切創(chuàng)建的(就像黃牛囤貨一樣)。

流只能遍歷一次

請(qǐng)注意,和迭代器類似,流只能遍歷一次。遍歷完之后,我們就說(shuō)這個(gè)流已經(jīng)被消費(fèi)掉了。你可以從原始數(shù)據(jù)源那里再獲得一個(gè)新的流來(lái)重新遍歷一遍,就像迭代器一樣(這里假設(shè)它是集合之類的可重復(fù)的源,如果是I/O通道就沒(méi)戲了)。例如以下代碼會(huì)拋出一個(gè)異常,說(shuō)流已被消費(fèi)掉了:

List names = Arrays.asList("Java8", "Lambdas", "In", "Action");
Stream s = names.stream();
s.forEach(System.out::println);
// 再繼續(xù)執(zhí)行一次,則會(huì)拋出異常
s.forEach(System.out::println);

千萬(wàn)要記住,它只能消費(fèi)一次!

外部迭代與內(nèi)部迭代

使用Collection接口需要用用戶去做迭代(比如用for-each),這個(gè)稱為外部迭代。反之,Stream庫(kù)使用內(nèi)部迭代,它幫你把迭代做了,還把得到的流值存在了某個(gè)地方,你只要給出一個(gè)函數(shù)說(shuō)要干什么就可以了。下面的代碼說(shuō)明了這種區(qū)別。

集合:使用for-each循環(huán)外部迭代:

// 集合:使用for-each循環(huán)外部迭代
List menu = Dish.MENU;
List names = new ArrayList<>();
for (Dish dish : menu) {
    names.add(dish.getName());
}

請(qǐng)注意, for-each 還隱藏了迭代中的一些復(fù)雜性。for-each結(jié)構(gòu)是一個(gè)語(yǔ)法糖,它背后的東西用Iterator對(duì)象表達(dá)出來(lái)更要丑陋得多。

集合:用背后的迭代器做外部迭代

List names = new ArrayList<>();
Iterator iterator = menu.iterator();
while(iterator.hasNext()) {
    Dish d = iterator.next();
    names.add(d.getName());
}

流:內(nèi)部迭代

List names = menu.stream()
                    .map(Dish::getName)
                    .collect(toList());

讓我們用一個(gè)比喻來(lái)解釋一下內(nèi)部迭代的差異和好處吧!比方說(shuō)你在和你兩歲的兒子說(shuō)話,希望他能把玩家收起來(lái)。

你:“兒子,我們把玩家收起來(lái)吧。地上還有玩具嗎?”
兒子:“有,球?!?你:“好,放進(jìn)盒子里。還有嗎?”
兒子:“有,那是我的飛機(jī)?!?你:“好,放進(jìn)盒子里。還有嗎?”
兒子:“有,我的書(shū)?!?你:“好,放進(jìn)盒子里。還有嗎?”
兒子:“沒(méi)了,沒(méi)有了。”
你:“好,我們收好啦!”

這正是你每天都要對(duì)Java集合做的。你外部迭代一個(gè)集合,顯式地取出每個(gè)項(xiàng)目再加以處理。如果,你對(duì)兒子說(shuō)“把地上的所有玩具都放進(jìn)盒子里收起來(lái)”就好了。內(nèi)部迭代比較好的原因有二:第一,兒子可以選擇一只手拿飛機(jī),另一只手拿球第二,他可以決定先拿離盒子最近的那個(gè)東西,然后再拿別的。同樣的道理,內(nèi)部迭代時(shí),項(xiàng)目可以透明地并行處理,或者用更優(yōu)化的順序進(jìn)行處理。要是用Java過(guò)去的那種外部迭代方法,這些優(yōu)化都是很困難的。這似乎有點(diǎn)兒雞蛋里挑骨頭,但這差不多就是Java 8引入流的理由了,Stream庫(kù)的內(nèi)部迭代可以自動(dòng)選擇一種適合你硬件的數(shù)據(jù)表示和并行實(shí)現(xiàn)。與此相反,一旦通過(guò)寫(xiě) for-each 而選擇了外部迭代,那你基本上就要自己管理所有的并行問(wèn)題了(自己管理實(shí)際上意味著“某個(gè)良辰吉日我們會(huì)把它并行化”或“開(kāi)始了關(guān)于任務(wù)和 synchronized 的漫長(zhǎng)而艱苦的斗爭(zhēng)”)。Java8需要一個(gè)類似于Collection 卻沒(méi)有迭代器的接口,于是就有了Stream!下面的圖說(shuō)明了流(內(nèi)部迭代)與集合(外部迭代)之間的差異。

我們已經(jīng)了解過(guò)了集合與流在概念上的差異,特別是利用內(nèi)部迭代:替你把迭代做了。但是,只有你已經(jīng)預(yù)先定義好了能夠隱藏迭代的操作集合。例如filter或map,這個(gè)才有用。大多數(shù)這類操作都接受Lambda表達(dá)式作為參數(shù),因此我們可以用前面所了解的知識(shí)來(lái)參數(shù)化其行為。

流操作

java.util.stream.Stream 中的 Stream 接口定義了許多操作。它們可以分為兩大類。我們?cè)賮?lái)看一下前面的例子:

List names = menu.stream()
                // 中間操作
                .filter(d -> d.getCalories() > 300)
                // 中間操作
                .map(Dish::getName)
                // 中間操作
                .limit(3)
                // 將Stream轉(zhuǎn)為L(zhǎng)ist
                .collect(toList());

filter、map和limit可以連成一條線,collect觸發(fā)流水線執(zhí)行并關(guān)閉它。可以連起來(lái)的稱為中間操作,關(guān)閉流的操作可以稱為終端操作。

中間操作

諸如filter和sorted等中間操作會(huì)返回一個(gè)流。讓多個(gè)操作可以連接起來(lái)形成一個(gè)查詢。重要的是,除非流水線上觸發(fā)一個(gè)終端操作,否則中間操作不會(huì)執(zhí)行任何處理它們懶得很。這就是因?yàn)橹虚g操作一般都可以合并起來(lái),在終端操作時(shí)一次性全部處理。

為了搞清楚流水線到底發(fā)生了什么,我們把代碼改一改,讓每個(gè)Lambda都打印出當(dāng)前處理的菜肴(就像很多演示和調(diào)試技巧一樣,這種編程風(fēng)格要是擱在生產(chǎn)代碼里那就嚇?biāo)廊肆?,但是學(xué)習(xí)的時(shí)候卻可以直接看清楚求值的順序):

List  names = menu.stream()
        .filter(d -> {
            System.out.println("filtering:" + d.getName());
            return d.getCalories() > 300;
        })
        .map(dish -> {
            System.out.println("mapping:" + dish.getName());
            return dish.getName();
        })
        .limit(3)
        .collect(toList());
System.out.println(names);

執(zhí)行結(jié)果:

filtering:pork
mapping:pork
filtering:beef
mapping:beef
filtering:chicken
mapping:chicken
[pork, beef, chicken]

從上面的打印結(jié)果,我們可以發(fā)現(xiàn)有好幾種優(yōu)化利用了流的延遲性質(zhì)。第一,盡管有很多熱量都高于300卡路里,但是只會(huì)選擇前三個(gè)!因?yàn)閘imit操作和一種稱為短路的技巧,第二,盡管filter和map是兩個(gè)獨(dú)立的操作,但是它們合并到同一次便利中了(我們把這種技術(shù)叫做循環(huán)合并)。

終端操作

終端操作會(huì)從流的流水線生產(chǎn)結(jié)果。其結(jié)果是任何不是流的值,比如List、Integer,甚至是void。例如,在下面的流水線中,foreachh返回的是一個(gè)void的終端操作,它對(duì)源中的每道菜應(yīng)用一個(gè)Lambda。把System.out.println()傳遞給foreach,并要求它打印出由menu生成的流中每一個(gè)Dish:

menu.stream().forEach(System.out::println);

為了檢驗(yàn)一下對(duì)終端操作已經(jīng)中間操作的理解,下面我們一起來(lái)看看一個(gè)例子:

下面哪些是中間操作哪些是終端操作?

long count = menu.stream()
            .filter(d -> d.getCalories() > 300)
            .distinct()
            .limit(3)
            .count();

答案:流水線中最后一個(gè)操作是count,它會(huì)返回一個(gè)long,這是一個(gè)非Stream的值。因此,它是終端操作。

使用流

總而言之,流的使用一般包括三件事:

一個(gè)數(shù)據(jù)源(比如集合)來(lái)執(zhí)行查詢

一個(gè)中間操作鏈,形成一條流的流水線

一個(gè)終端操作,執(zhí)行流水線,并能生成結(jié)果。

流的流水線背后的理念類似于構(gòu)建器模式。 在構(gòu)建器模式中有一個(gè)調(diào)用鏈用來(lái)設(shè)置一套配置(對(duì)流來(lái)說(shuō)這就是一個(gè)中間操作鏈),接著是調(diào)用built方法(對(duì)流來(lái)說(shuō)就是終端操作)。其實(shí),我們目前所看的Stream的例子用到的方法并不是它的全部,還有一些其他的一些操作。

在本章中,我們所接觸到的一些中間操作與終端操作:

中間:

操作 類型 返回類型 操作參數(shù) 函數(shù)描述
filter 中間 Stream Predicate T -> boolean
map 中間 Stream Function T -> R
limit 中間 Stream
sorted 中間 Stream Comparator (T, T) -> int
distinct 中間 Stream

終端:

操作 類型 目的
foreach 終端 消費(fèi)流中的每個(gè)元素并對(duì)其應(yīng)用 Lambda。這一操作返回 void
count 終端 返回流中元素的個(gè)數(shù)。這一操作返回 long
collect 終端 把流歸約成一個(gè)集合,比如 List 、 Map 甚至是 Integer

Stream是一個(gè)非常好用的一個(gè)新特性,它能幫助我們簡(jiǎn)化很多冗長(zhǎng)的代碼,提高我們代碼的可讀性。

本章總結(jié)

流是“從支持?jǐn)?shù)據(jù)處理操作的源生成的一系列元素”。

流利用內(nèi)部迭代:迭代通過(guò)filter、map、sorted等操作被抽象掉了。

流操作有兩類:中間操作和終端操作。

filter和map等中間操作會(huì)返回一個(gè)流,并可以鏈接在一起。可以用它們來(lái)設(shè)置一條流水線,但并不會(huì)生成任何結(jié)果。

forEach和count等終端操作會(huì)返回一個(gè)非流的值,并處理流水線以返回結(jié)果。

6.流中的元素是按需計(jì)算(懶加載)的。

代碼示例

Github: chap4

Gitee: chap4

公眾號(hào)

如果,你對(duì)Java8中的新特性很感興趣,你可以關(guān)注我的公眾號(hào)或者當(dāng)前的技術(shù)社區(qū)的賬號(hào),利用空閑的時(shí)間看看我的筆記,非常感謝!

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

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/76849.html

相關(guān)文章

  • Java8實(shí)戰(zhàn)》-讀書(shū)筆記第一章(02)

    摘要:實(shí)戰(zhàn)讀書(shū)筆記第一章從方法傳遞到接著上次的,繼續(xù)來(lái)了解一下,如果繼續(xù)簡(jiǎn)化代碼。去掉并且生成的數(shù)字是萬(wàn),所消耗的時(shí)間循序流并行流至于為什么有時(shí)候并行流效率比循序流還低,這個(gè)以后的文章會(huì)解釋。 《Java8實(shí)戰(zhàn)》-讀書(shū)筆記第一章(02) 從方法傳遞到Lambda 接著上次的Predicate,繼續(xù)來(lái)了解一下,如果繼續(xù)簡(jiǎn)化代碼。 把方法作為值來(lái)傳遞雖然很有用,但是要是有很多類似與isHeavy...

    lushan 評(píng)論0 收藏0
  • Java8實(shí)戰(zhàn)》-第五章讀書(shū)筆記(使用Stream-02)

    摘要:第三個(gè)問(wèn)題查找所有來(lái)自于劍橋的交易員,并按姓名排序。第六個(gè)問(wèn)題打印生活在劍橋的交易員的所有交易額。第八個(gè)問(wèn)題找到交易額最小的交易。 付諸實(shí)戰(zhàn) 在本節(jié)中,我們會(huì)將迄今學(xué)到的關(guān)于流的知識(shí)付諸實(shí)踐。我們來(lái)看一個(gè)不同的領(lǐng)域:執(zhí)行交易的交易員。你的經(jīng)理讓你為八個(gè)查詢找到答案。 找出2011年發(fā)生的所有交易,并按交易額排序(從低到高)。 交易員都在哪些不同的城市工作過(guò)? 查找所有來(lái)自于劍橋的交易...

    liangzai_cool 評(píng)論0 收藏0
  • 《java 8 實(shí)戰(zhàn)讀書(shū)筆記 -四章 引入

    摘要:第四章引入流一什么是流流是的新成員,它允許你以聲明性方式處理數(shù)據(jù)集合通過(guò)查詢語(yǔ)句來(lái)表達(dá),而不是臨時(shí)編寫(xiě)一個(gè)實(shí)現(xiàn)。 第四章 引入流 一、什么是流 流是Java API的新成員,它允許你以聲明性方式處理數(shù)據(jù)集合(通過(guò)查詢語(yǔ)句來(lái)表達(dá),而不是臨時(shí)編寫(xiě)一個(gè)實(shí)現(xiàn))。就現(xiàn)在來(lái)說(shuō),你可以把它們看成遍歷數(shù)據(jù)集的高級(jí)迭代器。此外,流還可以透明地并行處理,你無(wú)需寫(xiě)任何多線程代碼。 下面兩段代碼都是用來(lái)返回低...

    jeyhan 評(píng)論0 收藏0
  • Java8實(shí)戰(zhàn)》-第五章讀書(shū)筆記(使用Stream-01)

    摘要:跳過(guò)元素流還支持方法,返回一個(gè)扔掉了前個(gè)元素的流。歸約到目前為止,我們見(jiàn)到過(guò)的終端操作都是返回一個(gè)之類的或?qū)ο蟮?。這樣的查詢可以被歸類為歸約操作將流歸約成一個(gè)值。通過(guò)反復(fù)使用加法,你把一個(gè)數(shù)字列表歸約成了一個(gè)數(shù)字。 使用流 在上一篇的讀書(shū)筆記中,我們已經(jīng)看到了流讓你從外部迭代轉(zhuǎn)向內(nèi)部迭代。這樣,你就用不著寫(xiě)下面這樣的代碼來(lái)顯式地管理數(shù)據(jù)集合的迭代(外部迭代)了: /** * 菜單 ...

    OldPanda 評(píng)論0 收藏0
  • Java8實(shí)戰(zhàn)》-第六章讀書(shū)筆記(用收集數(shù)據(jù)-01)

    摘要:收集器用作高級(jí)歸約剛剛的結(jié)論又引出了優(yōu)秀的函數(shù)式設(shè)計(jì)的另一個(gè)好處更易復(fù)合和重用。更具體地說(shuō),對(duì)流調(diào)用方法將對(duì)流中的元素觸發(fā)一個(gè)歸約操作由來(lái)參數(shù)化。另一個(gè)常見(jiàn)的返回單個(gè)值的歸約操作是對(duì)流中對(duì)象的一個(gè)數(shù)值字段求和。 用流收集數(shù)據(jù) 我們?cè)谇耙徽轮袑W(xué)到,流可以用類似于數(shù)據(jù)庫(kù)的操作幫助你處理集合。你可以把Java 8的流看作花哨又懶惰的數(shù)據(jù)集迭代器。它們支持兩種類型的操作:中間操作(如 filt...

    EscapedDog 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<