成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Java 8新特性之旅:使用Stream API處理集合

開(kāi)發(fā) 后端
在這篇“Java 8新特性教程”系列文章中,我們會(huì)深入解釋,并通過(guò)代碼來(lái)展示,如何通過(guò)流來(lái)遍歷集合,如何從集合和數(shù)組來(lái)創(chuàng)建流,以及怎么聚合流的值。

在這篇“Java 8新特性教程”系列文章中,我們會(huì)深入解釋,并通過(guò)代碼來(lái)展示,如何通過(guò)流來(lái)遍歷集合,如何從集合和數(shù)組來(lái)創(chuàng)建流,以及怎么聚合流的值。

在之前的文章“遍歷、過(guò)濾、處理集合及使用Lambda表達(dá)式增強(qiáng)方法”中,我已經(jīng)深入解釋并演示了通過(guò)lambda表達(dá)式和方法引用來(lái)遍歷集合,使用predicate接口來(lái)過(guò)濾集合,實(shí)現(xiàn)接口的默認(rèn)方法,最后還演示了接口靜態(tài)方法的實(shí)現(xiàn)。

源代碼都在我的Github上:可以從 這里克隆。

內(nèi)容列表

  • 使用流來(lái)遍歷集合。

  • 從集合或數(shù)組創(chuàng)建流。

  • 聚合流中的值。

1. 使用流來(lái)遍歷集合

簡(jiǎn)介:

Java的集合框架,如List和Map接口及Arraylist和HashMap類,讓我們很容易地管理有序和無(wú)序集合。集合框架自引入的第一天 起就在 持續(xù)的改進(jìn)。在Java SE 8中,我們可以通過(guò)流的API來(lái)管理、遍歷和聚合集合。一個(gè)基于流的集合與輸入輸出流是不同的。

如何工作?

它采用一種全新的方式,將數(shù)據(jù)作為一個(gè)整體,而不是單獨(dú)的個(gè)體來(lái)處理。當(dāng)你使用流時(shí),你不需要關(guān)心循環(huán)或遍歷的細(xì)節(jié)。你可以直接從一個(gè)集合創(chuàng)建一個(gè) 流。然 后你就能用這個(gè)流來(lái)許多事件了,如遍歷、過(guò)濾及聚和。我將從項(xiàng)目 Java8Features 的 com.tm.java8.features.stream.traversing 包下的例子開(kāi)始。代碼在一個(gè)SequentialStream 類中,Java SE 8 中有兩種集合流,即串行流和并行流。

List<person> people = new ArrayList<>();

people.add(new Person("Mohamed", 69));
people.add(new Person("Doaa", 25));
people.add(new Person("Malik", 6));

Predicate<person> pred = (p) -> p.getAge() > 65;

displayPeople(people, pred);

...........

private static void displayPeople(List<person> people, Predicate<person> pred) {

     System.out.println("Selected:");
     people.forEach(p -> {
         if (pred.test(p)) {
             System.out.println(p.getName());
         }
     });
}

在這兩種流中,串行流相對(duì)比較簡(jiǎn)單,它類似一個(gè)迭代器,每次處理集合中的一個(gè)元素。但是語(yǔ)法與以前不同。在這段代碼中,我創(chuàng)建了 pepole 的數(shù)組列表,向上轉(zhuǎn)型為L(zhǎng)ist。它包含三個(gè) Person 類的實(shí)例。然后我們使用 Predicate 聲明一個(gè)條件,只有滿足這個(gè)條件的 people 才會(huì)顯示。在 displayPeople() 方法的48到52行循環(huán)遍歷該集合,挨個(gè)測(cè)試其中的每一項(xiàng)。運(yùn)行這段代碼,你將獲得如下的結(jié)果:

Selected:
Mohamed

我將會(huì)展示如何使用流來(lái)重構(gòu)這段代碼。首先,我注釋了這段代碼。然后,在這段注釋的代碼下,我開(kāi)始使用集合對(duì)象 people。然后我調(diào)用一個(gè) stream() 方法。一個(gè)stream對(duì)象,類似集合,也要聲明泛型。如果你從一個(gè)集合獲取流,則該流中每一項(xiàng)的類型與集合本身是一致的。我的集合是 Person 類的實(shí)例,所以流中也使用同樣的泛型類型。

System.out.println("Selected:");
//        people.forEach(p -> {
//            if (pred.test(p)) {
//                System.out.println(p.getName());
//            }
//        });

  people.stream().forEach(p -> System.out.println(p.getName()));
}

你可以調(diào)用一個(gè) stream() 方法來(lái)獲得了一個(gè)流對(duì)象,然后可以在該對(duì)象上進(jìn)行一些操作。我簡(jiǎn)單地調(diào)用了 forEach 方法,該方法需要一個(gè)Lamda表達(dá)式。我在參數(shù)中傳遞了一個(gè)Lamda表達(dá)式。列表中的每一項(xiàng)就是通過(guò)迭代器處理的每一項(xiàng)。處理過(guò)程是通過(guò)Lambda 操作符和方法實(shí)現(xiàn)來(lái)完成的。我簡(jiǎn)單使用system output來(lái)輸出每個(gè)人的名稱。保存并運(yùn)行這段代碼,輸出結(jié)果如下。因?yàn)闆](méi)有過(guò)濾,所以輸出了列表中所有元素。

Selected:
Mohamed
Doaa
Malik

現(xiàn)在,一旦有了一個(gè)流對(duì)象,就可以很容易使用 predicate 對(duì)象了。當(dāng)使用 for each 方法處理每一項(xiàng)時(shí),我不得不顯示調(diào)用 predicate 的 test 方法,但是使用流時(shí),你可以調(diào)用一個(gè)名為 filter 的方法。該方法接收一個(gè) predicate 對(duì)象,所有的 predicate 對(duì)象都有一個(gè) test 方法,所以它已經(jīng)知道怎樣去調(diào)用該方法。所以,我對(duì)該代碼做一點(diǎn)改動(dòng)。我將.forEach()方法下移了兩行,然后在中間的空白行,我調(diào)用了 filter 方法。

people.stream()
     .filter(pred)
     .forEach(p -> System.out.println(p.getName()));

filter方法接收一個(gè) predicate 接口的實(shí)例對(duì)象。我將 predicate 對(duì)象傳進(jìn)去。filtr 方法返回一個(gè)過(guò)濾后的流對(duì)象,在這個(gè)對(duì)象上我就可以去調(diào)用forEach()方法了。我運(yùn)行這段代碼,這次我只顯示集合中滿足預(yù)定義條件的項(xiàng)了。你可以在 流對(duì)象上做更多的事情。去看看 Java SE 8 API 中流的doc文檔吧。

Selected:
Mohamed

你將會(huì)看到除了過(guò)濾,你還可以做聚合、排序等其他的事情。在我總結(jié)這段演示之前,我想向你們展示一下串行流和并行流之前的重要區(qū)別。Java SE 8 的一個(gè)重要目標(biāo)就是改善多 CPU 系統(tǒng)的處理能力。Java 可在運(yùn)行期自動(dòng)協(xié)調(diào)多個(gè) CPU 的運(yùn)行。你需要做的所有事情僅僅是將串行流轉(zhuǎn)換為并行流。

從語(yǔ)法上講,有兩種方法來(lái)實(shí)現(xiàn)流的轉(zhuǎn)換。我復(fù)制一份串行流類。在包視圖窗口,我復(fù)制并粘貼該類,然后對(duì)它重命名,ParallelStream,打 開(kāi)這個(gè) 新的類。在這個(gè)版本中,刪除了注釋的代碼。我不再需要這些注釋了。現(xiàn)在就可以通過(guò)兩種方式創(chuàng)建并行流。第一種方式是調(diào)用集合中的 parallelStream()方法。現(xiàn)在我就擁有一個(gè)可以自動(dòng)分配處理器的流了。

private static void displayPeople(List<person> people, Predicate<person> pred) {
     System.out.println("Selected:");
     people.parallelStream()
             .filter(pred)
             .forEach(p -> System.out.println(p.getName()));
}

運(yùn)行這段代碼,就可以看到完全一致的結(jié)果,過(guò)濾然后返回?cái)?shù)據(jù)。

Selected:
Mohamed

第二種創(chuàng)建并行流的方式。再次調(diào)用 stream() 方法,然后在 stream 方法的基礎(chǔ)上調(diào)用 parallel() 方法,其本質(zhì)上做的事情是一樣的。開(kāi)始是一個(gè)串行的流,然后再將其轉(zhuǎn)換為并行流。但是它仍然是一個(gè)流。可以過(guò)濾,可以用之前的一樣方式去處理。只是現(xiàn)在的 流可以分解到多個(gè)處理起來(lái)處理。

people.stream()
      .parallel()
      .filter(pred)
      .forEach(p -> System.out.println(p.getName()));

總結(jié)

現(xiàn)在還沒(méi)有一個(gè)明確的規(guī)定來(lái)說(shuō)明在什么情況下并行流優(yōu)于串行流。這個(gè)依賴于數(shù)據(jù)的大小和復(fù)雜性以及硬件的處理能力。還有你運(yùn)行的多 CPU 系統(tǒng)。我可以給你的唯一建議是測(cè)試你的應(yīng)用和數(shù)據(jù)。建立一個(gè)基準(zhǔn)的、計(jì)時(shí)的操作。然后分別使用串行流和并行流,看哪一個(gè)更適合于你。

2、從集合或數(shù)組創(chuàng)建流

簡(jiǎn)介

Java SE 8’s stream API 是為了幫助管理數(shù)據(jù)集合而設(shè)計(jì)的,這些對(duì)象是指集合框架中的對(duì)象,例如數(shù)組列表或哈希表。但是,你也可以直接從數(shù)組創(chuàng)建流。

如何工作?

在 Java8Features 項(xiàng)目中的 eg.com.tm.java8.features.stream.creating 包下,我創(chuàng)建了一個(gè)名為ArrayToStream的類。在這個(gè)類的 main 方法中,我創(chuàng)建了一個(gè)包含三個(gè)元素的數(shù)組。每個(gè)元素都是Person類的一個(gè)實(shí)例對(duì)象。

public static void main(String args[]) {

    Person[] people = {
        new Person("Mohamed", 69),
        new Person("Doaa", 25),
        new Person("Malik", 6)};
    for (int i = 0; i < people.length; i++) {
        System.out.println(people[i].getInfo());
    }
}

該類中為私有成員創(chuàng)建了 setters 和 getters 方法,以及 getInfo() 方法,該方法返回一個(gè)拼接的字符串。

public String getInfo() {
    return name + " (" + age + ")";
}

現(xiàn)在,如果想使用流來(lái)處理這個(gè)數(shù)組,你可能認(rèn)為需要先將數(shù)組轉(zhuǎn)為數(shù)組列表,然后從這個(gè)列表創(chuàng)建流。但是,實(shí)際上你可以有兩種方式直接從數(shù)組創(chuàng)建流。第一方式,我不需要處理數(shù)據(jù)的那三行代碼,所以先注釋掉。然后,在這個(gè)下面,我聲明一個(gè)流類型的對(duì)象。

Stream 是 java.util.stream 下的一個(gè)接口。當(dāng)我按下 Ctrl+Space 并選取它的時(shí)候,會(huì)提示元素的泛型,這就是流管理的類型。在這里,元素的類型即為Person,與數(shù)組元素本身的類型是一致的。我將我新的流對(duì)象命名為 stream,所有的字母都是小寫(xiě)的。這就是第一種創(chuàng)建流的方法,使用流的接口,調(diào)用 of() 方法。注意,該方法存在兩個(gè)不同版本。

第一個(gè)是需要單個(gè)對(duì)象,第二個(gè)是需要多個(gè)對(duì)象。我使用一個(gè)參數(shù)的方法,所以傳遞一個(gè)名為 people 的數(shù)組,這就是我需要做的所有事情。Stream.of() 意思就是傳入一個(gè)數(shù)組,然后將該數(shù)組包裝在流中。現(xiàn)在,我就可以使用 lambda 表達(dá)式、過(guò)濾、方法引用等流對(duì)象的方法。我將調(diào)用流的 for each 方法,并傳入一個(gè) lambda 表達(dá)式,將當(dāng)前的 person 對(duì)象和 lambda 操作符后傳入后,就能獲取到 person 對(duì)象的信息。該信息是通過(guò)對(duì)象的 getInfo() 方法獲取到的。

Person[] people = {
        new Person("Mohamed", 69),
        new Person("Doaa", 25),
        new Person("Malik", 6)};

//        for (int i = 0; i < people.length; i++) {
//            System.out.println(people[i].getInfo());
//        }
        Stream<Person> stream = Stream.of(people);
        stream.forEach(p -> System.out.println(p.getInfo()));

保存并運(yùn)行這段代碼,就可獲取到結(jié)果。輸出的元素的順序與我放入的順序是一致的。這就是第一種方式:使用 Stream.of() 方法。

Mohamed (69)
Doaa (25)
Malik (6)

另一種方式與上面的方式實(shí)際上是相同的。復(fù)制上面的代碼,并注釋掉第一種方式。這次不使用 Stream.of() 方法,我們使用名為 Arrays 的類,該類位于 java.util 包下。在這個(gè)類上,可以調(diào)用名為 stream 的方法。注意,stream 方法可以包裝各種類型的數(shù)組,包括基本類型和復(fù)合類型。

//      Stream<person> stream = Stream.of(people);

        Stream<person> stream = Arrays.stream(people);
        stream.forEach(p -> System.out.println(p.getInfo()));

保存并運(yùn)行上面的代碼,流完成的事情與之前實(shí)質(zhì)上是一致的。

Mohamed (69)
Doaa (25)
Malik (6)

結(jié)論

所以,無(wú)論是 Stream.of() 還是 Arrays.stream(),所做的事情實(shí)質(zhì)上是一樣的。都是從一個(gè)基本類型或者復(fù)合對(duì)象類型的數(shù)組轉(zhuǎn)換為流對(duì)象,然后就可以使用 lambda 表達(dá)式、過(guò)濾、方法引用等功能了。

3、聚合流的值

簡(jiǎn)介

之前,我已經(jīng)描述過(guò)怎么使用一個(gè)流來(lái)迭代一個(gè)集合。你也可以使用流來(lái)聚合集合中的每一項(xiàng)。如計(jì)算總和、平均值、總數(shù)等等。當(dāng)你做這些操作的時(shí)候,弄明白并行流特性就非常重要。

如何工作?

我會(huì)在 Java8Features 項(xiàng)目的 eg.com.tm.java8.features.stream.aggregating 包下進(jìn)行演示。首先我們使用 ParallelStreams 類。在這個(gè)類的 main 方法中,我創(chuàng)建了一個(gè)包含字符串元素的數(shù)組列表。我簡(jiǎn)單地使用循環(huán)在列表中添加了10000個(gè)元素。然后在35和36行,我創(chuàng)建了一個(gè)流對(duì)象,并通過(guò) for each 方法挨個(gè)輸出流中每一項(xiàng)。

public static void main(String args[]) {

    System.out.println("Creating list");
    List<string> strings = new ArrayList<>();
    for (int i = 0; i < 10000; i++) {
        strings.add("Item " + i);
    }
    strings.stream()
           .forEach(str -> System.out.println(str));
}

運(yùn)行這段代碼后,就獲得了一個(gè)我所預(yù)期的結(jié)果。在屏幕上輸出的順序與添加到列表中的順序是一致的。

.........
Item 9982
Item 9983
Item 9984
Item 9985
Item 9986
Item 9987
Item 9988
Item 9989
Item 9990
Item 9991
Item 9992
Item 9993
Item 9994
Item 9995
Item 9996
Item 9997
Item 9998
Item 9999

現(xiàn)在,讓我們看一下當(dāng)轉(zhuǎn)換成并行流后會(huì)發(fā)生什么。正如我之前所描述的,我即可以調(diào)用parallelStream方法,也可以在流上調(diào)用parallel方法。

我將采用第二種方法。現(xiàn)在,我就可以使用并行流了,該流可以根據(jù)負(fù)載分配到多個(gè)處理器來(lái)處理。

strings.stream()
       .parallel()
       .forEach(str -> System.out.println(str));

再次運(yùn)行該段代碼,然后觀察會(huì)發(fā)生什么。注意,現(xiàn)在最后打印的元素不是列表中最后一個(gè)元素,最后一個(gè)元素應(yīng)該是9999。如果我滾動(dòng)輸出結(jié)果,就能發(fā)現(xiàn)處理過(guò)程以某種方式在循環(huán)跳動(dòng)。這是因?yàn)樵谶\(yùn)行時(shí)將數(shù)據(jù)劃分成了多個(gè)塊。

.........
Item 5292
Item 5293
Item 5294
Item 5295
Item 5296
Item 5297
Item 5298
Item 5299
Item 5300
Item 5301
Item 5302
Item 5303
Item 5304
Item 5305
Item 5306
Item 5307
Item 5308
Item 5309
Item 5310
Item 5311

然后,將數(shù)據(jù)塊分配給合適的處理器去處理。只有當(dāng)所有塊都處理完成了,才會(huì)執(zhí)行之后的代碼。本質(zhì)上講,這是在調(diào)用 forEach() 方法時(shí),將整個(gè)過(guò)程是根據(jù)需要來(lái)進(jìn)行劃分了。現(xiàn)在,這么做可能會(huì)提高性能,也可能不會(huì)。這依賴于數(shù)據(jù)集的大小以及你硬件的性能。通過(guò)這個(gè)例子,也可以看 出,如果需要按照添加的順序挨個(gè)處理每一項(xiàng),那么并行流可能就不合適了。

串行流能保證每次運(yùn)行的順序是一致的。但并行流,從定義上講,是一種更有效率的方式。所以并行流在聚合操作的時(shí)候非常有效。很適合將集合作為一個(gè)整體考慮,然后在該集合上進(jìn)行一些聚合操作的情況。我將會(huì)通過(guò)一個(gè)例子來(lái)演示集合元素的計(jì)數(shù)、求平均值及求和操作。

我們?cè)谶@個(gè)類的 main 方法中來(lái)計(jì)數(shù),開(kāi)始還是用相同的基礎(chǔ)代碼。創(chuàng)建10,000個(gè)字符串的列表。然后通過(guò)一個(gè) for each 方法循環(huán)處理每一項(xiàng)。

public static void main(String args[]) {

    System.out.println("Creating list");
    List<string> strings = new ArrayList<>();
    for (int i = 0; i < 10000; i++) {
        strings.add("Item " + i);
    }
    strings.stream()
           .forEach(str -> System.out.println(str));
}

在這個(gè)例子中,我想直接對(duì)集合元素進(jìn)行計(jì)數(shù),而不是挨個(gè)來(lái)處理。所以,我注釋掉原來(lái)的代碼,使用下面的代碼。因?yàn)椴荒軠?zhǔn)確的知道該集合到底有多少個(gè)元素。所以我使用長(zhǎng)整型變量來(lái)存儲(chǔ)結(jié)果。

我將這個(gè)變量命名為count,通過(guò)調(diào)用集合strings的.stream(), .count()方法,返回一個(gè)長(zhǎng)整型的值。然后將這個(gè)值與“count:”拼接起來(lái),再通過(guò)system的output來(lái)打印。

//      strings.stream()
//             .forEach(str -> System.out.println(str));
        long count = strings.stream().count();
        System.out.println("Count: " + count);

保存并運(yùn)行該段代碼,下面是輸出結(jié)果。集合中元素?cái)?shù)量的統(tǒng)計(jì)幾乎是瞬間完成。

Creating list
Count: 10000

現(xiàn)在對(duì)上面的代碼做一點(diǎn)小小的改動(dòng),增加兩個(gè)0。現(xiàn)在,開(kāi)始處理1000,000個(gè)字符串。我再次運(yùn)行這段代碼,也很快就返回結(jié)果了。

Creating list
Count: 1000000

現(xiàn)在,我使用并行流來(lái)處理,看會(huì)發(fā)生什么。我在下面增加 parallel 方法:

//      strings.stream()
//             .forEach(str -> System.out.println(str));
        long count = strings.stream().parallel().count();
        System.out.println("Count: " + count);

然后我運(yùn)行這段代碼,發(fā)現(xiàn)花費(fèi)的時(shí)間更長(zhǎng)一點(diǎn)了。現(xiàn)在,我做一個(gè)基準(zhǔn)測(cè)試,通過(guò)抓取操作前后的時(shí)間戳來(lái)觀察發(fā)生了什么。然后做一點(diǎn)數(shù)學(xué)的事情。不同 的系統(tǒng) 上,得到的結(jié)果可能不同。但是根據(jù)我的經(jīng)驗(yàn)來(lái)說(shuō),這種包含簡(jiǎn)單類型的簡(jiǎn)單集合,使用并行流并沒(méi)有太多的優(yōu)勢(shì)。不過(guò),我還是鼓勵(lì)你去自己做基準(zhǔn)測(cè)試,雖然有 點(diǎn)麻煩。 不過(guò)這也要你是如何去做的。

再讓我們看一下求和及求均值。我將使用 SumAndAverage 類。這次,我有一個(gè)包含三個(gè) person 對(duì)象的列表,每個(gè) person 對(duì)象的有不同的年齡值。我的目的是求三個(gè)年齡的和及年齡的平均值。我在所有的 person 對(duì)象都加入到列表之后加入了一行新的代碼。然后,我創(chuàng)建了一個(gè)名為sum的整型變量。

首先,我通過(guò) pepole.stream() 方法獲取一個(gè)流。在這個(gè)流基礎(chǔ)上,我可以調(diào)用 mapToInt() 方法。注意,還有兩個(gè)類似的 Map Method:mapToDouble() 和 mapToLong()。這些方法的目的就是,從復(fù)合類型中獲取簡(jiǎn)單的基本類型數(shù)據(jù),創(chuàng)建流對(duì)象。你可以用 lambda 表達(dá)式來(lái)完成這項(xiàng)工作。所以,我選擇 mapToInt() 方法,因?yàn)槊總€(gè)人的年齡都是整數(shù)。

關(guān)于 Lambda 表達(dá)式,開(kāi)始是一個(gè)代表當(dāng)前 person 的變量。然后,通過(guò) Lambda 操作符和 Lambda 表達(dá)式(p.getAge())返回一個(gè)整數(shù)。這種返回值,我們有時(shí)也叫做int字符串。也可以返回double字符串或其它類型。現(xiàn)在,由于已經(jīng)知道它 是一個(gè)數(shù)字類型的值,所以我可以調(diào)用 sum() 方法。現(xiàn)在,我就已經(jīng)將所有集合中 person 對(duì)象的年齡值全部加起來(lái)了。通過(guò)一條語(yǔ)句,我就可以用 System Output 來(lái)輸出結(jié)果了。我將求和的結(jié)果與“Total of ages”連接在一起輸出。

List<person> people = new ArrayList<>();
        people.add(new Person("Mohamed", 69));
        people.add(new Person("Doaa", 25));
        people.add(new Person("Malik", 6));

        int sum = people.stream()
                  .mapToInt(p -> p.getAge())
                  .sum();
        System.out.println("Total of ages " + sum);

保存并運(yùn)行上面的代碼。三個(gè)年齡的總和是100。

Total of ages 100

求這些值的平均值非常類似。但是,求平均值需要做除法操作,所以需要考慮除數(shù)為0的問(wèn)題,因此,當(dāng)你求平均值的時(shí)候,可以返回一個(gè)Optional的變量。

你可以使用多種數(shù)據(jù)類型。在計(jì)算平均值的時(shí)候,我想獲得一個(gè) doule 類型的值。所以,我創(chuàng)建了一個(gè) OptionalDouble 類型的變量。注意,還存在 Optional Int 和 Optional Long。我將平均值命名為 avg,使用的代碼與求和的代碼也是一致的,開(kāi)始用 people.stream()。在這個(gè)基礎(chǔ)上,再次使用 mapToInt()。并且傳遞了相同的 lambda 表達(dá)式,最后,調(diào)用 average 方法。

現(xiàn)在,獲得了一個(gè)OptionalDouble類型的變量。在處理這個(gè)變量前,你可以通過(guò) isPresent() 來(lái)確保它確實(shí)是一個(gè)double值。所以,我使用了一段 if/else 的模板代碼來(lái)處理。判定的條件是 avg.isPresent()。如果條件為真,就使用 System Output 輸出“Average”標(biāo)簽和平均值。在 else 子句中,我簡(jiǎn)單地打印“average wasn’t calculated”。

OptionalDouble avg = people.stream()
                .mapToInt(p -> p.getAge())
                .average();
if (avg.isPresent()) {
    System.out.println("Average: " + avg);
} else {
    System.out.println("average wasn't calculated");
}

現(xiàn)在,在這個(gè)例子中,我知道能成功,因?yàn)槲医o三個(gè)人的年齡都賦值了。但是,情況不總是這樣的。正如我前面說(shuō)的,存在除0的情況,這時(shí)你就不能獲取到一個(gè) double 類型返回值。我保存并運(yùn)行這段代碼,請(qǐng)注意 optional double 類,它是一個(gè)復(fù)合對(duì)象。

Total of ages 100
Average: OptionalDouble[33.333333333333336]

所以,真實(shí)的值被包含在該類型中,回到這段代碼,直接引用該對(duì)象,并調(diào)用 getAsDouble() 方法。

if (avg.isPresent()) {
    System.out.println("Average: " + avg.getAsDouble());
} else {
    System.out.println("average wasn't calculated");
}

現(xiàn)在,我就可以獲得 double 類型的值。我再次運(yùn)行這段代碼,輸出結(jié)果如下:

Total of ages 100
Average: 33.333333333333336

結(jié)論

通過(guò)流和 lambda 表達(dá)式,你可以用非常非常少的代碼就可以完成集合的聚合計(jì)算。

責(zé)任編輯:王雪燕 來(lái)源: ImportNew
相關(guān)推薦

2019-03-11 09:18:20

Java 8Stream數(shù)據(jù)結(jié)構(gòu)

2019-06-27 10:32:57

Java開(kāi)發(fā)代碼

2023-05-12 07:40:01

Java8API工具

2021-02-22 11:51:15

Java開(kāi)發(fā)代碼

2024-10-09 08:42:03

2014-07-15 14:48:26

Java8

2022-12-30 09:24:23

Java8Stream操作

2022-12-09 07:48:10

Java8Stream表達(dá)式

2014-10-20 13:57:59

JavaFX 8Java 8

2021-05-06 20:03:00

JavaStream代碼

2024-04-19 08:28:57

JavaAPI場(chǎng)景

2021-04-12 07:34:03

Java集合框架

2014-07-14 11:34:53

Java 8Nashorn

2024-02-04 08:35:03

APIJava 8數(shù)據(jù)庫(kù)

2024-02-02 11:18:37

Java 8API對(duì)象

2013-05-02 09:14:19

Java 8Java 8的新特性

2014-03-19 11:04:14

Java 8Java8特性

2014-04-15 15:45:22

Java8Java8教程

2014-05-05 09:58:01

2014-04-16 07:43:31

Java 8JRE
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 成人av影院| 国产午夜精品一区二区三区嫩草 | a毛片| 超级碰在线 | 精品久久久久久久人人人人传媒 | 亚洲综合视频一区 | 97国产在线视频 | www.色综合| 亚洲高清一区二区三区 | 国产偷录视频叫床高潮对白 | 成人伊人 | 91av视频在线播放 | 色资源站| 久久精品国产久精国产 | 国产精品入口麻豆www | 亚洲精品视 | 中文久久| 国产精品观看 | 女人av| 在线一区 | 亚洲影视在线 | 国产视频线观看永久免费 | 亚洲精品电影网在线观看 | 91精品国产综合久久精品 | 中文字幕一区二区三区四区五区 | 久久成人18免费网站 | 国产网站在线免费观看 | 午夜电影网 | 国产精品免费看 | 亚洲第一av网站 | 日韩福利 | av福利网站| 91网站在线观看视频 | 色综合美女 | 国产精品a级 | 久久亚洲视频网 | 高清人人天天夜夜曰狠狠狠狠 | 欧美日韩电影免费观看 | 在线视频国产一区 | 色爱区综合 | 日本成人免费网站 |