Java8體驗(yàn)

最近開始研究Java8济锄,現(xiàn)將其體驗(yàn)分享如下: ??


?1.為什么需要使用Java8? ? ?

1996 年1 月盗扒,Java 1.0 發(fā)布管钳,此后計(jì)算機(jī)編程領(lǐng)域發(fā)生了翻天覆地的變化榜晦。商業(yè)發(fā)展需要更復(fù)雜的應(yīng)用虏肾,大多數(shù)程序都跑在功能強(qiáng)大的多核CPU 的機(jī)器上廓啊。帶有高效運(yùn)行時(shí)編譯器的Java 虛擬機(jī)(JVM)的出現(xiàn),使程序員將更多精力放在編寫干凈封豪、易于維護(hù)的代碼上谴轮,而不是思考如何將每一個(gè)CPU 時(shí)鐘周期、每字節(jié)內(nèi)存物盡其用吹埠。多核CPU 的興起成為了不容回避的事實(shí)第步。涉及鎖的編程算法不但容易出錯(cuò),而且耗費(fèi)時(shí)間缘琅。人們開發(fā)了java.util.concurrent 包和很多第三方類庫(kù)粘都,試圖將并發(fā)抽象化,幫助程序員寫出在多核CPU 上運(yùn)行良好的程序刷袍。很可惜翩隧,到目前為止,我們的成果還遠(yuǎn)遠(yuǎn)不夠呻纹。? ? ? ??

開發(fā)類庫(kù)的程序員使用Java 時(shí)堆生,發(fā)現(xiàn)抽象級(jí)別還不夠专缠。處理大型數(shù)據(jù)集合就是個(gè)很好的例子,面對(duì)大型數(shù)據(jù)集合顽频,Java 還欠缺高效的并行操作藤肢。開發(fā)者能夠使用Java 8 編寫復(fù)雜的集合處理算法,只需要簡(jiǎn)單修改一個(gè)方法糯景,就能讓代碼在多核CPU 上高效運(yùn)行嘁圈。為了編寫這類處理批量數(shù)據(jù)的并行類庫(kù),需要在語(yǔ)言層面上修改現(xiàn)有的Java:增加Lambda 表達(dá)式蟀淮。? ? ? ??

當(dāng)然最住,這樣做是有代價(jià)的,程序員必須學(xué)習(xí)如何編寫和閱讀使用Lambda 表達(dá)式的代碼怠惶,但是涨缚,這不是一樁賠本的買賣。與手寫一大段復(fù)雜策治、線程安全的代碼相比脓魏,學(xué)習(xí)一點(diǎn)新語(yǔ)法和一些新習(xí)慣容易很多。開發(fā)企業(yè)級(jí)應(yīng)用時(shí)通惫,好的類庫(kù)和框架極大地降低了開發(fā)時(shí)間和成本茂翔,也為開發(fā)易用且高效的類庫(kù)掃清了障礙。? ? ? ?

對(duì)于習(xí)慣了面向?qū)ο缶幊痰拈_發(fā)者來(lái)說(shuō)履腋,抽象的概念并不陌生珊燎。面向?qū)ο缶幊淌菍?duì)數(shù)據(jù)進(jìn)行抽象,而函數(shù)式編程是對(duì)行為進(jìn)行抽象∽窈現(xiàn)實(shí)世界中悔政,數(shù)據(jù)和行為并存,程序也是如此延旧,因此這兩種編程方式我們都得學(xué)谋国。這種新的抽象方式還有其他好處。不是所有人都在編寫性能優(yōu)先的代碼垄潮,對(duì)于這些人來(lái)說(shuō)烹卒,函數(shù)式編程帶來(lái)的好處尤為明顯。程序員能編寫出更容易閱讀的代碼——這種代碼更多地表達(dá)了業(yè)務(wù)邏輯的意圖弯洗,而不是它的實(shí)現(xiàn)機(jī)制。易讀的代碼也易于維護(hù)逢勾、更可靠牡整、更不容易出錯(cuò)。? ? ?

?在寫回調(diào)函數(shù)和事件處理程序時(shí)溺拱,程序員不必再糾纏于匿名內(nèi)部類的冗繁和可讀性逃贝,函數(shù)式編程讓事件處理系統(tǒng)變得更加簡(jiǎn)單谣辞。能將函數(shù)方便地傳遞也讓編寫惰性代碼變得容易,惰性代碼在真正需要時(shí)才初始化變量的值沐扳。Java 8 還讓集合類可以擁有一些額外的方法:default 方法泥从。程序員在維護(hù)自己的類庫(kù)時(shí),可以使用這些方法沪摄。 ? ? ? ?


2.函數(shù)式編程? ? ?

每個(gè)人對(duì)函數(shù)式編程的理解不盡相同躯嫉。但其核心是:在思考問題時(shí),使用不可變值和函數(shù)杨拐,函數(shù)對(duì)一個(gè)值進(jìn)行處理祈餐,映射成另一個(gè)值。不同的語(yǔ)言社區(qū)往往對(duì)各自語(yǔ)言中的特性孤芳自賞『逄眨現(xiàn)在談Java 程序員如何定義函數(shù)式編程還為時(shí)尚早帆阳,但是,這根本不重要屋吨!我們關(guān)心的是如何寫出好代碼蜒谤,而不是符合函數(shù)式編程風(fēng)格的代碼。本書將重點(diǎn)放在函數(shù)式編程的實(shí)用性上至扰,包括可以被大多數(shù)程序員理解和使用的技術(shù)鳍徽,幫助他們寫出易讀、易維護(hù)的代碼渊胸。? ? ??


3.Lambda表達(dá)式? ? ??

Lambda 表達(dá)式是?? 一個(gè)匿名方法旬盯,將行為像數(shù)據(jù)一樣進(jìn)行傳遞。? ? ?

?A.Lambda表達(dá)式的常見結(jié)構(gòu):BinaryOperatoradd = (x, y) → x + y翎猛。

B.函數(shù)接口指僅具有單個(gè)抽象方法的接口胖翰,用來(lái)表示 Lambda表達(dá)式的類型。


4.流

內(nèi)部迭代將更多控制權(quán)交給了集合類切厘。

A.和 Iterator 類似萨咳,Stream 是一種內(nèi)部迭代方式。

B.將 Lambda表達(dá)式和 Stream 上的方法結(jié)合起來(lái)疫稿,可以完成很多常見的集合操作培他。


5.類庫(kù)

使用為基本類型定?? 制的 Lambda表達(dá)式和 Stream,如IntStream 可以顯著提升系統(tǒng)性能遗座。

A.默認(rèn)方法是指接口中定義的包含方法體的方法舀凛,方法名有 default 關(guān)鍵字做前綴。

B.在一個(gè)值可能為空的建模情況下途蒋,使用 Optional 對(duì)象能替代使用 null 值猛遍。


6.高級(jí)集合類和收集器

方法引用是一種引用方法的輕量級(jí)語(yǔ)法,形如:ClassName::methodName。

A.收集器可用來(lái)計(jì)算流的最終值懊烤,是 reduce 方法的模擬梯醒。

B.Java 8 提供了收集多種容器類型的方式,同時(shí)允許用戶自定義收集器腌紧。


7.數(shù)據(jù)并行化

數(shù)據(jù)并行化是把?? 工作拆分茸习,同時(shí)在多核 CPU上執(zhí)行的方式。

A.如果使用流編寫代碼壁肋,可通過(guò)調(diào)用 parallel 或者 parallelStream 方法實(shí)現(xiàn)數(shù)據(jù)并行化操作号胚。

B. 影響性能的五要素是:數(shù)據(jù)大小、源數(shù)據(jù)結(jié)構(gòu)墩划、值是否裝箱涕刚、可用的 CPU 核數(shù)量,以及處理每個(gè)元素所花的時(shí)間乙帮。


8.重構(gòu)代碼和測(cè)試

重構(gòu)遺留代碼時(shí)考慮如何使用?? Lambda 表達(dá)式杜漠,有一些通用的模式。

A.如果想要對(duì)復(fù)雜一點(diǎn)的 Lambda表達(dá)式編寫單元測(cè)試察净,將其抽取成一個(gè)常規(guī)的方法驾茴。

B.peek 方法能記錄中間值,在調(diào)試時(shí)非常有用氢卡。


9.設(shè)計(jì)架構(gòu)和原則

Lambda 表達(dá)式能讓很多現(xiàn)有設(shè)計(jì)模?? 式更簡(jiǎn)單锈至、可讀性更強(qiáng),尤其是命令者模式译秦。

A.在 Java 8 中峡捡,創(chuàng)建領(lǐng)域?qū)S谜Z(yǔ)言有更多的靈活性。

B.在 Java 8 中筑悴,有應(yīng)用 SOLID 原則的新機(jī)會(huì)们拙。


10.關(guān)于響應(yīng)式編程RxJava

構(gòu)建復(fù)雜并行操作的另外一種方案是使用Future。Future 像一張欠條阁吝,方法不是返回一個(gè)值砚婆,而是返回一個(gè)Future 對(duì)象,該對(duì)象第一次創(chuàng)建時(shí)沒有值突勇,但以后能拿它“換回”一個(gè)值装盯。調(diào)用Future 對(duì)象的get 方法獲取值,它會(huì)阻塞當(dāng)前線程甲馋,直到返回值埂奈。可惜定躏,和回調(diào)一樣挥转,組合Future 對(duì)象時(shí)也有問題海蔽,我們會(huì)快速瀏覽這些可能碰到的問題共屈。

這些問題的解決之道是CompletableFuture绑谣,它結(jié)合了Future 對(duì)象打欠條的主意和使用回調(diào)處理事件驅(qū)動(dòng)的任務(wù)。其要點(diǎn)是可以組合不同的實(shí)例拗引,而不用擔(dān)心末日金字塔問題。

CompletableFuture 背后的概念可以從單一的返回值推廣到數(shù)據(jù)流,這就是響應(yīng)式編程斑芜。響應(yīng)式編程其實(shí)是一種聲明式編程方法哥童,它讓程序員以自動(dòng)流動(dòng)的變化和數(shù)據(jù)流來(lái)編程。你可以將電子表格想象成一個(gè)使用響應(yīng)式編程的例子哼凯。如果在單元格C1 中鍵入=B1+5欲间,其實(shí)是在告訴電子表格將B1 中的值加5,然后將結(jié)果存入C1断部。而且猎贴,將來(lái)B1 中的值變化后,電子表格會(huì)自動(dòng)刷新C1 中的值蝴光。

RxJava 類庫(kù)將這種響應(yīng)式的理念移植到了JVM她渴。我們這里不會(huì)深入類庫(kù),只描述其中的一些關(guān)鍵概念蔑祟。

RxJava 類庫(kù)引入了一個(gè)叫作Observable 的類趁耗,該類代表了一組待響應(yīng)的事件,可以理解為一沓欠條疆虚。在Observable 對(duì)象和第3 章講述的Stream 接口之間有很強(qiáng)的關(guān)聯(lián)苛败。

兩種情況下,都需要使用Lambda 表達(dá)式將行為和一般的操作關(guān)聯(lián)径簿、都需要將高階函數(shù)鏈接起來(lái)定義完成任務(wù)的規(guī)則罢屈。實(shí)際上,Observable 定義的很多操作都和Stream 的相同:map牍帚、filter儡遮、reduce。

最大的不同在于用例暗赶。Stream 是為構(gòu)建內(nèi)存中集合的計(jì)算流程而設(shè)計(jì)的鄙币,而RxJava 則是為了組合異步和基于事件的系統(tǒng)流程而設(shè)計(jì)的。它沒有取數(shù)據(jù)蹂随,而是把數(shù)據(jù)放進(jìn)去十嘿。換個(gè)角度理解RxJava,它是處理一組值岳锁,而CompletableFuture 用來(lái)處理一個(gè)值绩衷。


11.何時(shí)使用新技術(shù)

新技術(shù)那么美好,這是否意味著大家明天就要扔掉現(xiàn)有的Java EE 或者Spring 企業(yè)級(jí)Web 應(yīng)用呢?答案當(dāng)然是否定的咳燕。

即使不去考慮CompletableFuture 和RxJava 相對(duì)較新勿决,使用它們依然有一定的復(fù)雜度。它們用起來(lái)比到處顯式使用Future 和回調(diào)簡(jiǎn)單招盲,但對(duì)很多問題來(lái)說(shuō)低缩,傳統(tǒng)的阻塞式Web 應(yīng)用開發(fā)技術(shù)就足夠了。如果還能用曹货,就別修理咆繁。

事件驅(qū)動(dòng)和響應(yīng)式應(yīng)用正在變得越來(lái)越流行,而且經(jīng)常會(huì)是為你的問題建模的最好方式之一顶籽。響應(yīng)式編程宣言(http://www.reactivemanifesto.org/)鼓勵(lì)大家使用這種方式編寫更多應(yīng)用玩般,如果它適合你的待解問題,那么就應(yīng)該使用礼饱。相比阻塞式設(shè)計(jì)坏为,有兩種情況可能特別適合使用響應(yīng)式或事件驅(qū)動(dòng)的方式來(lái)思考。

第一種情況是業(yè)務(wù)邏輯本身就使用事件來(lái)描述慨仿。Twitter 就是一個(gè)經(jīng)典例子久脯。Twitter 是一種訂閱文字流信息的服務(wù),用戶彼此之間推送信息镰吆。使用事件驅(qū)動(dòng)架構(gòu)編寫應(yīng)用帘撰,能準(zhǔn)確地為業(yè)務(wù)建模。圖形化展示股票價(jià)格可能是另一個(gè)例子万皿,每一次價(jià)格的變動(dòng)都可認(rèn)為是一個(gè)事件摧找。

另一種顯然的用例是應(yīng)用需要同時(shí)處理大量I/O 操作。阻塞式I/O 需要同時(shí)使用大量線程牢硅,這會(huì)導(dǎo)致大量鎖之間的競(jìng)爭(zhēng)和太多的上下文切換蹬耘。如果想要處理成千上萬(wàn)的連接,非阻塞式I/O 通常是更好的選擇减余。


12.使用Lambda表達(dá)式編寫并發(fā)程序

使用基于Lambda 表達(dá)式的回調(diào)综苔,很容易實(shí)現(xiàn)事件驅(qū)動(dòng)架構(gòu)。

A.CompletableFuture 代表了 IOU位岔,使用 Lambda表達(dá)式能方便地組合如筛、合并。

B.Observable 繼承了 CompletableFuture 的概念抒抬,用來(lái)處理數(shù)據(jù)流杨刨。


13.下一步計(jì)劃

A. 向其他程序員(朋友或同事)解釋什么是Lambda ?? 表達(dá)式,為什么會(huì)對(duì)它產(chǎn)生興趣擦剑。

B.嘗試將目前從事的項(xiàng)目部署到 Java 8 環(huán)境下妖胀。如果現(xiàn)有單元測(cè)試已經(jīng)能運(yùn)行在持續(xù)集成系統(tǒng)Jenkins 下芥颈,那么在多個(gè)版本的Java 上構(gòu)建程序也易如反掌。

C. 使用新的 Stream 和 Collector赚抡,開始重構(gòu)真實(shí)產(chǎn)品中的遺留代碼爬坑。它既可以是感興趣的開放源碼項(xiàng)目,也可以是當(dāng)前從事的項(xiàng)目怕品,前提是第一步里已經(jīng)部署成功一個(gè)測(cè)試環(huán)境妇垢。

D.如果還沒準(zhǔn)備好大規(guī)模遷往Java 8,那么在分支上使用Java 8 做一些原型會(huì)是個(gè)不錯(cuò)的開始肉康。

E.有沒有一些大規(guī)模處理數(shù)據(jù)的代碼?或者代碼中存在并發(fā)問題灼舍?試著使用 Stream 處理數(shù)據(jù)吼和,或使用RxJava 中新的并發(fā)特性,也可以使用CompletableFuture 類骑素,來(lái)重構(gòu)你的代碼炫乓。

F.選擇一個(gè)熟悉的代碼庫(kù),分析它的設(shè)計(jì)和架構(gòu)献丑。

從宏觀上看末捣,有沒有更好的實(shí)現(xiàn)方法?

能否簡(jiǎn)化設(shè)計(jì)创橄?

能否減少實(shí)現(xiàn)某功能所需的代碼量箩做?

怎樣讓代碼更易讀?

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末妥畏,一起剝皮案震驚了整個(gè)濱河市邦邦,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌醉蚁,老刑警劉巖燃辖,帶你破解...
    沈念sama閱讀 222,378評(píng)論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異网棍,居然都是意外死亡黔龟,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,970評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門滥玷,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)氏身,“玉大人,你說(shuō)我怎么就攤上這事罗捎」矍” “怎么了?”我有些...
    開封第一講書人閱讀 168,983評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵桨菜,是天一觀的道長(zhǎng)豁状。 經(jīng)常有香客問我捉偏,道長(zhǎng),這世上最難降的妖魔是什么泻红? 我笑而不...
    開封第一講書人閱讀 59,938評(píng)論 1 299
  • 正文 為了忘掉前任夭禽,我火速辦了婚禮,結(jié)果婚禮上谊路,老公的妹妹穿的比我還像新娘讹躯。我一直安慰自己,他們只是感情好缠劝,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,955評(píng)論 6 398
  • 文/花漫 我一把揭開白布潮梯。 她就那樣靜靜地躺著,像睡著了一般惨恭。 火紅的嫁衣襯著肌膚如雪秉馏。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,549評(píng)論 1 312
  • 那天脱羡,我揣著相機(jī)與錄音萝究,去河邊找鬼。 笑死锉罐,一個(gè)胖子當(dāng)著我的面吹牛帆竹,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播脓规,決...
    沈念sama閱讀 41,063評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼栽连,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了抖拦?” 一聲冷哼從身側(cè)響起升酣,我...
    開封第一講書人閱讀 39,991評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎态罪,沒想到半個(gè)月后噩茄,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,522評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡复颈,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,604評(píng)論 3 342
  • 正文 我和宋清朗相戀三年绩聘,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片耗啦。...
    茶點(diǎn)故事閱讀 40,742評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡凿菩,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出帜讲,到底是詐尸還是另有隱情衅谷,我是刑警寧澤,帶...
    沈念sama閱讀 36,413評(píng)論 5 351
  • 正文 年R本政府宣布似将,位于F島的核電站获黔,受9級(jí)特大地震影響蚀苛,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜玷氏,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,094評(píng)論 3 335
  • 文/蒙蒙 一堵未、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧盏触,春花似錦渗蟹、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,572評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至诗宣,卻和暖如春膘怕,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背召庞。 一陣腳步聲響...
    開封第一講書人閱讀 33,671評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留来破,地道東北人篮灼。 一個(gè)月前我還...
    沈念sama閱讀 49,159評(píng)論 3 378
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像徘禁,于是被迫代替她去往敵國(guó)和親诅诱。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,747評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,317評(píng)論 25 707
  • lambda表達(dá)式(又被成為“閉包”或“匿名方法”)方法引用和構(gòu)造方法引用擴(kuò)展的目標(biāo)類型和類型推導(dǎo)接口中的默認(rèn)方法...
    183207efd207閱讀 1,486評(píng)論 0 5
  • 原文鏈接:https://github.com/EasyKotlin 值就是函數(shù)送朱,函數(shù)就是值娘荡。所有函數(shù)都消費(fèi)函數(shù),...
    JackChen1024閱讀 5,988評(píng)論 1 17
  • 嗡嗡響金黃身子尾帶針天露一線光傾巢而出吻花忙 天下瓜果一遍紅有誰(shuí)知道是你功紅了瓜果甜滿勺一年四季勞 花兒點(diǎn)頭你效勞...
    蔣光頭jL94430閱讀 490評(píng)論 8 20
  • 崔雪。我的女朋友回怜,我最愛的女人之一大年。 我和她認(rèn)識(shí)超過(guò)100天了,期間我們通過(guò)微信聯(lián)系玉雾,我們打過(guò)幾次電話翔试,最長(zhǎng)一次通...
    張學(xué)武閱讀 465評(píng)論 0 0