成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

Java8新特性第3章(Stream API)

andycall / 1502人閱讀

摘要:另外,像這樣生成值的操作和這樣產(chǎn)生副作用的操作都是天然急性求值,因?yàn)樗鼈儽仨氁a(chǎn)生具體的結(jié)果。這樣可以大大減少維持中間結(jié)果所帶來的開銷?,F(xiàn)在我們需要篩選出含有平米以上房源的小區(qū),并按照小區(qū)名排序。

轉(zhuǎn)載請(qǐng)注明出處:https://zhuanlan.zhihu.com/p/20540202

Stream作為Java8的新特性之一,他與Java IO包中的InputStream和OutputStream完全不是一個(gè)概念。Java8中的Stream是對(duì)集合功能的一種增強(qiáng),主要用于對(duì)集合對(duì)象進(jìn)行各種非常便利高效的聚合和大批量數(shù)據(jù)的操作。結(jié)合Lambda表達(dá)式可以極大的提高開發(fā)效率和代碼可讀性。

假設(shè)我們需要把一個(gè)集合中的所有形狀設(shè)置成紅色,那么我們可以這樣寫

for (Shape shape : shapes){
    shape.setColor(RED)
}

如果使用Java8擴(kuò)展后的集合框架則可以這樣寫:

shapes.foreach(s -> s.setColor(RED));

__第一種__寫法我們叫外部迭代,for-each調(diào)用shapesiterator()依次遍歷集合中的元素。這種外部迭代有一些問題:

for循環(huán)是串行的,而且必須按照集合中元素的順序依次進(jìn)行;

集合框架無法對(duì)控制流進(jìn)行優(yōu)化,例如通過排序、并行、短路求值以及惰性求值改善性能。

上面這兩個(gè)問題我們會(huì)在后面的文章中逐步解答。

__第二種__寫法我們叫內(nèi)部迭代,兩段代碼雖然看起來只是語法上的區(qū)別,但實(shí)際上他們內(nèi)部的區(qū)別其實(shí)非常大。用戶把對(duì)操作的控制權(quán)交還給類庫,從而允許類庫進(jìn)行各種各樣的優(yōu)化(例如亂序執(zhí)行、惰性求值和并行等等)??偟膩碚f,內(nèi)部迭代使得外部迭代中不可能實(shí)現(xiàn)的優(yōu)化成為可能。

外部迭代同時(shí)承擔(dān)了做什么(把形狀設(shè)為紅色)和怎么做(得到Iterator實(shí)例然后依次遍歷),而內(nèi)部迭代只負(fù)責(zé)做什么,而把怎么做留給類庫。這樣代碼會(huì)變得更加清晰,而集合類庫則可以在內(nèi)部進(jìn)行各種優(yōu)化。

一、什么是Stream

Stream不是集合元素,它也不是數(shù)據(jù)結(jié)構(gòu)、不能保存數(shù)據(jù),它更像一個(gè)更高級(jí)的Interator。Stream提供了強(qiáng)大的數(shù)據(jù)集合操作功能,并被深入整合到現(xiàn)有的集合類和其它的JDK類型中。流的操作可以被組合成流水線(Pipeline)。拿前面的例子來說,如果我只想把藍(lán)色改成紅色:

shapes.stream()
      .filter(s -> s.getColor() == BLUE)
      .forEach(s -> s.setColor(RED));

Collection上調(diào)用stream()會(huì)生成該集合元素的流,接下來filter()操作會(huì)產(chǎn)生只包含藍(lán)色形狀的流,最后,這些藍(lán)色形狀會(huì)被forEach操作設(shè)為紅色。

如果我們想把藍(lán)色的形狀提取到新的List里,則可以:

List blue = shapes.stream()
                          .filter(s -> s.getColor() == BLUE)
                          .collect(Collectors.toList());

collect()操作會(huì)把其接收的元素聚集到一起(這里是List),collect()方法的參數(shù)則被用來指定如何進(jìn)行聚集操作。在這里我們使用toList()以把元素輸出到List中。

如果每個(gè)形狀都被保存在Box里,然后我們想知道哪個(gè)盒子至少包含一個(gè)藍(lán)色形狀,我們可以這么寫:

Set hasBlueShape = shapes.stream()
                               .filter(s -> s.getColor() == BLUE)
                              .map(s -> s.getContainingBox())
                              .collect(Collectors.toSet());

map()操作通過映射函數(shù)(這里的映射函數(shù)接收一個(gè)形狀,然后返回包含它的盒子)對(duì)輸入流里面的元素進(jìn)行依次轉(zhuǎn)換,然后產(chǎn)生新流。

如果我們需要得到藍(lán)色物體的總重量,我們可以這樣表達(dá):

int sum = shapes.stream()
                .filter(s -> s.getColor() == BLUE)
                .mapToInt(s -> s.getWeight())
                .sum();
二、Stream vs Collection

流(Stream)和集合(Collection)的區(qū)別:

Collection主要用來對(duì)元素進(jìn)行管理和訪問;

Stream并不支持對(duì)其元素進(jìn)行直接操作和直接訪問,而只支持通過聲明式操作在其之上進(jìn)行運(yùn)算后得到結(jié)果;

Stream不存儲(chǔ)值

對(duì)Stream的操作會(huì)產(chǎn)生一個(gè)結(jié)果,但是Stream并不會(huì)改變數(shù)據(jù)源;

大多數(shù)Stream的操作(filter,map,sort等)都是以惰性的方式實(shí)現(xiàn)的。這使得我們可以使用一次遍歷完成整個(gè)流水線操作,并可以用短路操作提供更高效的實(shí)現(xiàn)。

三、惰性求值 vs 急性求值

filter()map()這樣的操作既可以被急性求值(以filter()為例,急性求值需要在方法返回前完成對(duì)所有元素的過濾),也可以被惰性求值(用Stream代表過濾結(jié)果,當(dāng)且僅當(dāng)需要時(shí)才進(jìn)行過濾操作)在實(shí)際中進(jìn)行惰性運(yùn)算可以帶來很多好處。比如說,如果我們進(jìn)行惰性過濾,我們就可以把過濾和流水線里的其它操作混合在一起,從而不需要對(duì)數(shù)據(jù)進(jìn)行多遍遍歷。相類似的,如果我們?cè)谝粋€(gè)大型集合里搜索第一個(gè)滿足某個(gè)條件的元素,我們可以在找到后直接停止,而不是繼續(xù)處理整個(gè)集合。(這一點(diǎn)對(duì)無限數(shù)據(jù)源是很重要,惰性求值對(duì)于有限數(shù)據(jù)源起到的是優(yōu)化作用,但對(duì)無限數(shù)據(jù)源起到的是決定作用,沒有惰性求值,對(duì)無限數(shù)據(jù)源的操作將無法終止)

對(duì)于filter()map()這樣的操作,我們很自然的會(huì)把它當(dāng)成是惰性求值操作,不過它們是否真的是惰性取決于它們的具體實(shí)現(xiàn)。另外,像sum()這樣生成值的操作和forEach()這樣產(chǎn)生副作用的操作都是__天然急性求值__,因?yàn)樗鼈儽仨氁a(chǎn)生具體的結(jié)果。

我們拿下面這段代碼舉例:

int sum = shapes.stream()
                .filter(s -> s.getColor() == BLUE)
                .mapToInt(s -> s.getWeight())
                .sum();

這里的filter()map()都是惰性的,這就意味著在調(diào)用sum()之前不會(huì)從數(shù)據(jù)源中提取任何元素。在sum()操作之后才會(huì)把filter()map()sum()放在對(duì)數(shù)據(jù)源一次遍歷中。這樣可以大大減少維持中間結(jié)果所帶來的開銷。

四、舉個(gè)栗子?

前面長(zhǎng)篇大論的介紹概念實(shí)在太枯燥,為了方便大家理解我們用Streams API來實(shí)現(xiàn)一個(gè)具體的業(yè)務(wù)場(chǎng)景。

假設(shè)我們有一個(gè)房源庫項(xiàng)目,這個(gè)房源庫中有一系列的小區(qū),每個(gè)小區(qū)都有小區(qū)名和房源列表,每套房子又有價(jià)格、面積等屬性。現(xiàn)在我們需要篩選出含有100平米以上房源的小區(qū),并按照小區(qū)名排序。

我們先來看看不用Streams API如何實(shí)現(xiàn):

List result = new ArrayList<>();
for (Community community : communities) {
        for (House house : community.houses) {
            if (house.area > 100) {
                result.add(community);
                break;
            }
        }
    }
    Collections.sort(result, new Comparator() {
        @Override
        public int compare(Community c1, Community c2) {
            return c1.name.compareTo(c2.name);
        }
    });
    return result;      

如果使用Streams API:

return communities.stream()
          .filter(c -> c.houses.stream().anyMatch(h -> h.area>100))
          .sorted(Comparator.comparing(c -> c.name))
          .collect(Collectors.toList());

如果大家喜歡這一系列的文章,歡迎關(guān)注我的知乎專欄、GitHub、簡(jiǎn)書博客。

知乎專欄:https://zhuanlan.zhihu.com/baron

GitHub:https://github.com/BaronZ88

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

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/66489.html

相關(guān)文章

  • 在Android項(xiàng)目中使用Java8

    摘要:現(xiàn)在爸爸終于讓平臺(tái)支持了,這篇文章中便來和大家聊聊如何在項(xiàng)目中配置使用。要想在項(xiàng)目中使用的新特性,需要將你的升級(jí)到及以上版本,并采用新的編譯。 轉(zhuǎn)載請(qǐng)注明出處:https://zhuanlan.zhihu.com/p/23279894 前言 在過去的文章中我介紹過Java8的一些新特性,包括: Java8新特性第1章(Lambda表達(dá)式) Java8新特性第2章(接口默認(rèn)方法) J...

    junnplus 評(píng)論0 收藏0
  • Java8特性1(Lambda表達(dá)式)

    摘要:一表達(dá)式匿名內(nèi)部類最大的問題在于其冗余的語法,比如前面的中五行代碼僅有一行是在執(zhí)行任務(wù)。總結(jié)基于詞法作用域的理念,表達(dá)式不可以掩蓋任何其所在上下文的局部變量。 轉(zhuǎn)載請(qǐng)注明出處:https://zhuanlan.zhihu.com/p/20540175 在介紹Lambda表達(dá)式之前,我們先來看只有單個(gè)方法的Interface(通常我們稱之為回調(diào)接口): public interface...

    ningwang 評(píng)論0 收藏0
  • Java8實(shí)戰(zhàn)》-十一筆記(CompletableFuture:組合式異步編程)

    摘要:組合式異步編程最近這些年,兩種趨勢(shì)不斷地推動(dòng)我們反思我們?cè)O(shè)計(jì)軟件的方式。第章中介紹的分支合并框架以及并行流是實(shí)現(xiàn)并行處理的寶貴工具它們將一個(gè)操作切分為多個(gè)子操作,在多個(gè)不同的核甚至是機(jī)器上并行地執(zhí)行這些子操作。 CompletableFuture:組合式異步編程 最近這些年,兩種趨勢(shì)不斷地推動(dòng)我們反思我們?cè)O(shè)計(jì)軟件的方式。第一種趨勢(shì)和應(yīng)用運(yùn)行的硬件平臺(tái)相關(guān),第二種趨勢(shì)與應(yīng)用程序的架構(gòu)相關(guān)...

    hlcfan 評(píng)論0 收藏0
  • Java學(xué)習(xí)路線總結(jié),搬磚工逆襲Java架構(gòu)師(全網(wǎng)最強(qiáng))

    摘要:哪吒社區(qū)技能樹打卡打卡貼函數(shù)式接口簡(jiǎn)介領(lǐng)域優(yōu)質(zhì)創(chuàng)作者哪吒公眾號(hào)作者架構(gòu)師奮斗者掃描主頁左側(cè)二維碼,加入群聊,一起學(xué)習(xí)一起進(jìn)步歡迎點(diǎn)贊收藏留言前情提要無意間聽到領(lǐng)導(dǎo)們的談話,現(xiàn)在公司的現(xiàn)狀是碼農(nóng)太多,但能獨(dú)立帶隊(duì)的人太少,簡(jiǎn)而言之,不缺干 ? 哪吒社區(qū)Java技能樹打卡?【打卡貼 day2...

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

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

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<