Java 實戰, 2/e (Modern Java in Action: Lambda, streams, functional and reactive programming, 2/e)

[英]拉烏爾–加布里埃爾·烏爾瑪 [意]馬里奧·富斯科 [英]艾倫·米克羅夫特

  • Java 實戰, 2/e (Modern Java in Action: Lambda, streams, functional and reactive programming, 2/e)-preview-1
  • Java 實戰, 2/e (Modern Java in Action: Lambda, streams, functional and reactive programming, 2/e)-preview-2
Java 實戰, 2/e (Modern Java in Action: Lambda, streams, functional and reactive programming, 2/e)-preview-1

買這商品的人也買了...

商品描述

本書全面介紹了Java 8、9、10版本的新特性,包括Lambda表達式、方法引用、流、默認方法、Optional、CompletableFuture以及新的日期和時間API,是程序員瞭解Java新特性的經典指南。全書共分六個部分:基礎知識、使用流進行函數式數據處理、使用流和Lambda進行高效編程、無所不在的Java、提升Java的並發性、函數式編程以及Java未來的演進。

作者簡介

拉烏爾–加布里埃爾·烏爾瑪(Raoul-Gabriel Urma),劍橋大學計算機科學博士,軟件工程師,培訓師,現任Cambridge Spark公司CEO。在谷歌、eBay、甲骨文和高盛等大公司工作過,並參與過多個創業項目。活躍在技術社區,經常撰寫技術文章,多次受邀在國際會議上做技術講座。
馬里奧·富斯科(Mario Fusco),Red Hat高級軟件工程師,負責JBoss規則引擎Drools的核心開發。擁有豐富的Java開發經驗,曾領導媒體公司、金融部門等多個行業的企業級項目開發。對函數式編程和領域特定語言等有濃厚興趣,並創建了開放源碼庫lambdaj。

艾倫·米克羅夫特(Alan Mycroft),劍橋大學計算機實驗室計算學教授,劍橋大學羅賓遜學院研究員,歐洲編程語言和系統協會聯合創始人,樹莓派基金會聯合創始人和理事。發表過大約100篇研究論文,指導過20多篇博士論文。他的研究主要關注編程語言及其語義、優化和實施。他與業界聯繫緊密,曾於學術休假期間在AT&T實驗室和英特爾工作,還創立了Codemist公司,該公司設計了最初的ARM C編譯器Norcroft。

陸明剛,畢業於四川大學,目前在Dell EMC中國卓越研發集團任高級主管工程師,曾任趨勢科技中國軟件研發中心技術經理,在信息科學和工程領域有十餘年的實踐和研究經驗,擁有多項中國及美國專利。關注JVM性能調優和大數據及其實踐,喜歡挖掘技術背後的內幕並樂此不疲。
勞佳,上海交通大學碩士,現任SAP(美國)高級軟件支持顧問。業餘愛好語言、數學、設計,英、法雙語譯者,近年翻譯出版了《諮詢的奧秘》《卓越程序員密碼》《計算進化史:改變數學的命運》等書。

目錄大綱

 

第一部分基礎知識


第1章Java 8、9、10以及11的變化2
1.1為什麼要關心Java的變化2
1.2 Java怎麼還在變4
1.2.1 Java在編程語言生態系統中的位置5
1.2.2流處理6
1.2.3用行為參數化把代碼傳遞給方法7
1.2.4並行與共享的可變數據8
1.2.5 Java需要演變9
1.3 Java中的函數9
1.3.1方法和Lambda作為一等值10
1.3.2傳遞代碼:一個例子11
1.3.3從傳遞方法到Lambda 13
1.4流14
1.5默認方法及Java模塊17
1.6來自函數式編程的其他好思想19
1.7小結20


第2章通過行為參數化傳遞代碼22
2.1應對不斷變化的需求23
2.1.1初試牛刀:篩選綠蘋果23
2.1.2再展身手:把顏色作為參數23
2.1.3第三次嘗試:對你能想到的每個屬性做篩選24
2.2行為參數化25
2.3對付囉唆30
2.3.1匿名類30
2.3.2第五次嘗試:使用匿名類31
2.3.3第六次嘗試:使用Lambda表達式32
2.3.4第七次嘗試:將List類型抽象化33
2.4真實的例子33
2.4.1用Comparator來排序33
2.4.2用Runnable執行代碼塊34
2.4.3通過Callable返回結果35
2.4.4 GUI事件處理35
2.5小結36


第3章Lambda表達式37
3.1 Lambda管中窺豹37
3.2在哪里以及如何使用Lambda 40
3.2.1函數式接口40
3.2.2函數描述符42
3.3把Lambda付諸實踐:環繞執行模式44
3.3.1第1步:記得行為參數化44
3.3.2第2步:使用函數式接口來傳遞行為45
3.3.3第3步:執行一個行為45
3.3.4第4步:傳遞Lambda 46
3.4使用函數式接口47
3.4.1 Predicate 47
3.4.2 Consumer 47
3.4.3 Function 48
3.5類型檢查、類型推斷以及限制52
3.5.1類型檢查52
3.5.2同樣的Lambda,不同的函數式接口53
3.5.3類型推斷55
3 .5.4使用局部變量56
3.6方法引用57
3.6.1管中窺豹57
3.6.2構造函數引用60
3.7 Lambda和方法引用實戰62
3.7.1第1步:傳遞代碼62
3.7.2第2步:使用匿名類62
3.7.3第3步:使用Lambda表達式62
3.7.4第4步:使用方法引用63
3.8複合Lambda表達式的有用方法63
3.8.1比較器複合64
3.8.2謂詞複合64
3.8.3函數複合65
3.9數學中的類似思想66
3.9.1積分66
3.9.2與Java 8的Lambda聯繫起來68
3. 10小結68


第二部分使用流進行函數式數據處理


第4章引入流72
4.1流是什麼72
4.2流簡介76
4.3流與集合78
4.3.1只能遍歷一次79
4 .3.2外部迭代與內部迭代80
4.4流操作82
4.4.1中間操作83
4.4.2終端操作84
4.4.3使用流84
4.5路線圖85
4.6小結85


第5章使用流86
5.1篩選87
5.1.1用謂詞篩選87
5.1.2篩選各異的元素87
5.2流的切片88
5.2.1使用謂詞對流進行切片88
5 .2.2截短流90
5.2.3跳過元素90
5.3映射91
5.3.1對流中每一個元素應用函數91
5.3.2流的扁平化92
5.4查找和匹配95
5.4.1檢查謂詞是否至少匹配一個元素95
5.4.2檢查謂詞是否匹配所有元素96
5.4.3查找元素96
5.4.4查找第一個元素97
5.5歸約98
5.5.1元素求和98
5.5.2最大值和最小值100
5.6付諸實踐103
5.6.1領域:交易員和交易103
5.6.2解答104
5. 7數值流106
5.7.1原始類型流特化107
5.7.2數值範圍108
5.7.3數值流應用:勾股數108
5.8構建流111
5.8.1由值創建流111
5.8.2由可空對象創建流111
5.8.3由數組創建流112
5.8.4由文件生成流112
5.8.5由函數生成流:創建無限流113
5.9概述116
5.10小結116


第6章用流收集數據118
6.1收集器簡介119
6 .1.1收集器用作高級歸約119
6.1.2預定義收集器120
6.2歸約和匯總121
6.2.1查找流中的最大值和最小值121
6.2.2匯總122
6.2.3連接字符串123
6.2.4廣義的歸約匯總124
6.3分組127
6.3.1操作分組的元素128
6.3.2多級分組130
6.3.3按子組收集數據131
6.4分區134
6.4.1分區的優勢135
6.4.2將數字按質數和非質數分區136
6.5收集器接口138
6.5.1理解Collector接口聲明的方法139
6.5.2全部融合到一起143
6.6開發你自己的收集器以獲得更好的性能144
6.6.1僅用質數做除數145
6.6.2比較收集器的性能148
6.7小結150


第7章並行數據處理與性能151
7.1並行流152
7.1.1將順序流轉換為並行流52
7.1.2測量流性能154
7.1.3正確使用並行流158
7.1.4高效使用並行流159
7. 2分支/合併框架161
7.2.1使用RecursiveTask 161
7.2.2使用分支/合併框架的最佳做法164
7.2.3工作竊取165
7.3 Spliterator 166
7.3.1拆分過程167
7.3.2實現你自己的Spliterator 168
7.4小結173


第三部分使用流和Lambda進行高效編程


第8章Collection API的增強功能176
8.1集合工廠176
8.1.1 List工廠177
8.1.2 Set工廠178
8.1.3 Map工廠179
8.2使用List和Set 180
8.2.1 removeIf方法180
8.2.2 replaceAll方法181
8.3使用Map 181
8.3. 1 forEach方法182
8.3.2排序182
8.3.3 getOrDefault方法183
8.3.4計算模式183
8.3.5刪除模式184
8.3.6替換模式185
8.3.7 merge方法185
8.4改進的ConcurrentHashMap 187
8.4.1歸約和搜索187
8.4.2計數188
8. 4.3 Set視圖188
8.5小結188


第9章重構、測試和調試189
9.1為改善可讀性和靈活性重構代碼189
9.1.1改善代碼的可讀性190
9.1. 2從匿名類到Lambda表達式的轉換190
9.1.3從Lambda表達式到方法引用的轉換191
9.1.4從命令式的數據處理切換到Stream 193
9.1.5增加代碼的靈活性193
9.2使用Lambda重構面向對象的設計模式195
9.2.1策略模式196
9.2.2模板方法197
9.2.3觀察者模式198
9.2.4責任鏈模式201
9 .2.5工廠模式202
9.3測試Lambda表達式204
9.3.1測試可見Lambda函數的行為204
9.3.2測試使用Lambda的方法的行為205
9.3.3將復雜的Lambda表達式分為不同的方法205
9.3.4高階函數的測試206
9.4調試206
9.4.1查看棧跟踪206
9.4.2使用日誌調試208
9.5小結209


第10章基於Lambda的領域特定語言210
10 .1領域特定語言212
10.1.1 DSL的優點和弊端212
10.1.2 JVM中已提供的DSL解決方案214
10.2現代Java API中的小型DSL 217
10.2.1把Stream API當成DSL去操作集合219
10.2.2將Collectors作為DSL匯總數據220
10.3使用Java創建DSL的模式與技巧221
10.3.1方法鏈接224
10.3.2使用嵌套函數226
10. 3.3使用Lambda表達式的函數序列228
10.3.4把它們都放到一起230
10.3.5在DSL中使用方法引用232
10.4 Java 8 DSL的實際應用234
10.4.1 jOOQ 235
10.4.2 Cucumber 236
10.4.3 Spring Integration 238
10.5小結239


第四部分無所不在的Java


第11章用Optional取代null 242
11.1如何為缺失的值建模243
11.1.1採用防禦式檢查減少NullPointerException 243
11.1.2 null帶來的種種問題245
11.1.3其他語言中null的替代品245
11. 2 Optional類入門246
11.3應用Optional的幾種模式248
11.3.1創建Optional對象248
11.3.2使用map從Optional對像中提取和轉換值248
11.3.3使用flatMap鏈接Optional對象249
11.3.4操縱由Optional對象構成的Stream 253
11.3.5默認行為及解引用Optional對象254
11.3.6兩個Optional對象的組合255
11.3.7使用filter剔除特定的值257
11.4使用Optional的實戰示例258
11.4.1用Optional封裝可能為null的值259
11.4.2異常與Optional的對比259
11.4.3基礎類型的Optional對象,以及為什麼應該避免使用它們260
11.4.4把所有內容整合起來260
11.5小結262


第12章新的日期和時間API 263
12.1 LocalDate、LocalTime、LocalDateTime、Instant、Duration以及Period 264
12.1.1使用LocalDate和LocalTime 264
12.1.2合併日期和時間265
12.1.3機器的日期和時間格式266
12.1 .4定義Duration或Period 267
12.2操縱、解析和格式化日期268
12.2.1使用TemporalAdjuster 270
12.2.2打印輸出及解析日期–時間對象272
12.3處理不同的時區和曆法274
12.3.1使用時區274
12.3.2利用和UTC/格林尼治時間的固定偏差計算時區275
12.3.3使用別的日曆系統276
12.4小結277


第13章默認方法278
13.1不斷演進的API 280
13.1.1初始版本的API 281
13.1.2第二版API 281
13.2概述默認方法283
13.3默認方法的使用模式285
13.3.1可選方法285
13.3.2行為的多繼承286
13.4解決衝突的規則289
13.4.1解決問題的三條規則289
13.4.2選擇提供了最具體實現的默認方法的接口290
13.4.3衝突及如何顯式地消除歧義291
13.4.4菱形繼承問題293
13.5小結294


第14章Java模塊系統295
14.1模塊化的驅動力:軟件的推理295
14.1.1關注點分離295
14.1.2信息隱藏296
14.1.3 Java軟件296
14.2為什麼要設計Java模塊系統297
14.2.1模塊化的局限性297
14.2.2單體型的JDK 298
14.2.3與OSGi的比較299
14.3 Java模塊:全局視圖300
14.4使用Java模塊系統開發應用301
14.4.1從頭開始搭建一個應用302
14.4.2細粒度和粗粒度的模塊化303
14.4.3 Java模塊系統基礎303
14.5使用多個模塊304
14.5.1 exports子句304
14.5.2 requires子句305
14.5.3命名306
14.6編譯及打包306
14.7自動模塊310
14.8模塊聲明及子句311
14.8.1 requires 311
14.8.2 exports 311
14.8.3 requires的傳遞311
14.8.4 exports to 312
14.8.5 open和opens 312
14.8.6 uses和provides 313
14.9通過一個更複雜的例子了解更多313
14.10小結314


第五部分提升Java的並發性


第15章CompletableFuture及反應式編程背後的概念316
15.1為支持並發而不斷演進的Java 318
15.1.1線程以及更高層的抽象319
15.1.2執行器和線程池320
15.1.3其他的線程抽象:非嵌套方法調用322
15.1.4你希望線程為你帶來什麼324
15.2同步及異步API 324
15.2.1 Future風格的API 326
15.2.2反應式風格的API 327
15.2.3有害的睡眠及其他阻塞式操作328
15.2.4實戰驗證329
15.2. 5如何使用異步API進行異常處理330
15.3 “線框–管道”模型331
15.4為並發而生的CompletableFuture和結合器332
15.5 “發布–訂閱”以及反應式編程335
15.5.1示例:對兩個流求和337
15.5.2背壓341
15.5.3一種簡單的真實背壓341
15.6反應式系統和反應式編程342
15.7路線圖342
15.8小結343


第16章CompletableFuture:組合式異步編程344
16.1 Future接口344
16.1.1 Future接口的局限性346
16.1.2使用CompletableFuture構建異步應用346
16.2實現異步API 347
16.2.1將同步方法轉換為異步方法348
16.2.2錯誤處理350
16.3讓你的代碼免受阻塞之苦352
16.3.1使用並行流對請求進行並行操作353
16.3.2使用CompletableFuture發起異步請求353
16.3.3尋找更好的方案355
16.3.4使用定制的執行器356
16.4對多個異步任務進行流水線操作358
16.4.1實現折扣服務358
16.4.2使用Discount服務359
16.4.3構造同步和異步操作360
16.4.4將兩個CompletableFuture對象整合起來,無論它們是否存在依賴363
16.4.5對Future和Completable-Future的回顧364
16.4.6高效地使用超時機制365
16.5響應CompletableFuture的completion事件366
16.5.1對最佳價格查詢器應用的優化367
16 .5.2付諸實踐368
16.6路線圖369
16.7小結369


第17章反應式編程370
17.1反應式宣言371
17.1.1應用層的反應式編程371
17.1.2反應式系統373
17.2反應式流以及Flow API 373
17.2.1 Flow類374
17.2.2創建你的第一個反應式應用377
17.2.3使用Processor轉換數據381
17.2 .4為什麼Java並未提供Flow API的實現383
17.3使用反應式庫RxJava 384
17.3.1創建和使用Observable 385
17.3.2轉換及整合多個Observable 392


第六部分函數式編程以及Java未來的演進


第18章函數式的思考396
18.1實現和維護系統396
18.1.1共享的可變數據397
18.1.2聲明式編程398
18.1.3為什麼要採用函數式編程399
18.2什麼是函數式編程399
18.2.1函數式Java編程400
18.2.2引用透明性402
18.2.3面向對象的編程和函數式編程的對比402
18.2.4函數式編程實戰403
18.3遞歸和迭代405
18.4小結408


第19章函數式編程的技巧409
19.1無處不在的函數409
19.1. 1高階函數410
19.1.2柯里化411
19.2持久化數據結構412
19.2.1破壞式更新和函數式更新的比較413
19.2.2另一個使用Tree的例子415
19 .2.3採用函數式的方法416
19.3 Stream的延遲計算418
19.3.1自定義的Stream 418
19.3.2創建你自己的延遲列表420
19.4模式匹配425
19.4. 1訪問者模式425
19.4.2用模式匹配力挽狂瀾426
19.5雜項429
19.5.1緩存或記憶表429
19.5.2 “返回同樣的對象”意味著什麼430
19.5.3結合器431
19.6小結432


第20章面向對象和函數式編程的混合:Java和Scala的比較433
20.1 Scala簡介434
20.1.1你好,啤酒434
20.1.2基礎數據結構:List、Set、Map、Tuple 、Stream以及Option 436
20.2函數440
20.2.1 Scala中的一等函數441
20.2.2匿名函數和閉包442
20.2.3柯里化443
20.3類和trait 444
20 .3.1更加簡潔的Scala類445
20.3.2 Scala的trait與Java 8的接口對比446
20.4小結447


第21章結論以及Java的未來448
21.1回顧Java 8的語言特性448
21 .1.1行為參數化(Lambda以及方法引用) 449
21.1.2流449
21.1.3 CompletableFuture 450
21.1.4 Optional 450
21.1.5 Flow API 451
21.1.6默認方法451
21.2 Java 9的模塊系統451
21.3 Java 10的局部變量類型推斷453
21.4 Java的未來454
21.4.1聲明處型變454
21.4.2模式匹配454
21.4.3更加豐富的泛型形式455
21.4.4對不變性的更深層支持457
21.4.5值類型458
21.5讓Java發展得更快461
21.6寫在最後的話462


附錄A其他語言特性的更新463
附錄B其他類庫的更新467
附錄C如何以並發方式在同一個流上執行多種操作475
附錄D Lambda表達式和JVM字節碼483