內容提要
《Java函式式編程》並不是一本關於Java的書,而是一本關於函式式編程的書。作者由淺入深地介紹了函式式編程的思維方式,並引導讀者通過易於掌握的例子、練習和圖表來學習和鞏固函式式編程的基本原則和最佳實踐。讀者甚至可以在閱讀的同時編寫出自己的函式式類庫!
目錄
第1章 什麼是函式式編程 1
1.1 函式式編程是什麼 2
1.2 編寫沒有副作用的程式 4
1.3 引用透明如何讓程式更安全 6
1.4 函式式編程的優勢 7
1.5 用代換模型來推斷程式 8
1.6 將函式式原則套用於一個簡單的例子 9
1.7 抽象到極致 15
1.8 總結 16
第2章 在Java中使用函式 17
2.1 什麼是函式 .18
2.1.1 現實世界裡的函式 18
2.2 Java中的函式 24
2.2.1 函式式的方法 24
2.2.2 Java的函式式接口與匿名類 30
2.2.3 複合函式 31
2.2.4 多態函式 32
2.2.5 通過 lambda簡化代碼 33
2.3 高級函式特性 36
2.3.1 多參函式怎么樣 36
2.3.2 套用柯里化函式 37
2.3.3 高階函式 38
2.3.4 多態高階函式 39
2.3.5 使用匿名函式 43
2.3.6 局部函式 45
2.3.7 閉包 .46
2.3.8 部分函式套用和自動柯里化 48
2.3.9 交換部分套用函式的參數 53
2.3.10 遞歸函式 54
2.3.11 恆等函式 56
2.4 Java 8的函式式接口 58
2.5 調試lambda ..59
2.6 總結 62
第3章 讓Java更加函式式 63
3.1 使標準控制結構具有函式式風格 64
3.2 抽象控制結構 65
3.2.1 清理代碼 69
3.2.2 if … else的另一種方式 73
3.3 抽象疊代 78
3.3.1 使用映射抽象列表操作 79
3.3.2 創建列表 80
3.3.3 使用 head和 tail操作 81
3.3.4 函式式地添加列表元素 83
3.3.5 化簡和摺疊列表 83
3.3.6 複合映射和映射複合 90
3.3.7 對列表套用作用 91
3.3.8 處理函式式的輸出 92
3.3.9 構建反遞歸列表 93
3.4 使用正確的類型 97
3.4.1 標準類型的問題 97
3.4.2 定義值類型 99
3.4.3 值類型的未來 103
3.5 總結 103
第4章 遞歸、反遞歸和記憶化 104
4.1 理解反遞歸和遞歸 105
4.1.1 探討反遞歸和遞歸的加法例子 105
4.1.2 在 Java中實現遞歸 106
4.1.3 使用尾調用消除 107
4.1.4 使用尾遞歸方法和函式 107
4.1.5 抽象遞歸 108
4.1.6 為基於棧的遞歸方法使用一個直接替代品 112
4.2 使用遞歸函式 115
4.2.1 使用局部定義的函式 115
4.2.2 使函式成為尾遞歸 116
4.2.3 雙遞歸函式:斐波那契數列示例 117
4.2.4 讓列表的方法變成棧安全的遞歸 120
4.3 複合大量函式 123
4.4 使用記憶化 127
4.4.1 命令式編程中的記憶化 127
4.4.2 遞歸函式的記憶化 128
4.4.3 自動記憶化 130
4.5 總結 136
第5章 用列表處理數據 138
5.1 如何對數據集合進行分類 138
5.1.1 不同的列表類型 139
5.1.2 對列表性能的相對期望 140
5.1.3 時間與空間,時間與複雜度的取捨 .141
5.1.4 直接修改 142
5.1.5 持久化數據結構 143
5.2 一個不可變、持久化的單鍊表實現 144
5.3 在列表操作中共享數據 148
5.3.1 更多列表操作 150
5.4 使用高階函式遞歸摺疊列表 155
5.4.1 基於堆的 foldRight遞歸版 162
5.4.2 映射和過濾列表 164
5.5 總結 167
第6章 處理可選數據 168
6.1 空指針的問題 169
6.2 空引用的替代方案 171
6.3 Option數據類型 174
6.3.1 從 Option中取值 176
6.3.2 將函式套用於可選值 178
6.3.3 複合 Option處理 179
6.3.4 Option的用例 181
6.3.5 複合 Option的其他方法 186
6.3.6 複合 Option和 List 189
6.4 Option的其他實用程式 191
6.4.1 檢查是 Some還是 None 191
6.4.2 equals和 hashcode 192
6.5 如何及何時使用Option 193
6.6 總結 195
第7章 處理錯誤和異常 197
7.1 待解決的問題 197
7.2 Either類型 ..199
7.2.1 複合 Either 200
7.3 Result類型 .203
7.3.1 為 Result類添加方法 204
7.4 Result模式 .206
7.5 Result處理進階 213
7.5.1 套用斷言 214
7.5.2 映射 Failure 215
7.5.3 增加工廠方法 218
7.5.4 套用作用 220
7.5.5 Result複合進階 222
7.6 總結 226
第8章 列表處理進階 228
8.1 length的問題 229
8.1.1 性能問題 229
8.1.2 記憶化的優點 230
8.1.3 記憶化的缺點 230
8.1.4 實際性能 232
8.2 複合List和Result 233
8.2.1 List中返回 Result的方法 233
8.2.2 將 List<Result>轉換為 Result<List> 235
8.3 抽象常見列表用例 238
8.3.1 壓縮和解壓縮列表 238
8.3.2 通過索引訪問元素 241
8.3.3 拆分列表 244
8.3.4 搜尋子列表 248
8.3.5 使用列表的其他函式 249
8.4 自動並行處理列表 254
8.4.1 並非所有的計算都可以並行化 254
8.4.2 將列表拆分為子列表 254
8.4.3 並行處理子列表 256
8.5 總結 258
第9章 使用惰性 259
9.1 理解嚴格和惰性 259
9.1.1 Java是一門嚴格的語言 260
9.1.2 嚴格帶來的問題 261
9.2 實現惰性 ...263
9.3 只有惰性才能做到的事 264
9.4 為何不要用Java 8中的Stream 265
9.5 創建一個惰性列表數據結構 266
9.5.1 記憶已計算的值 268
9.5.2 對流的操作 271
9.6 惰性的真正本質 274
9.6.1 摺疊流 277
9.7 處理無限流 282
9.8 避免null引用和可變欄位 285
9.9 總結 287
第10章 用樹進行更多數據處理 289
10.1 二叉樹 290
10.1.1 平衡樹和非平衡樹 291
10.1.2 大小、高度和深度 291
10.1.3 葉樹 292
10.1.4 有序二叉樹或二叉搜尋樹 292
10.1.5 插入順序 293
10.1.6 樹的遍歷順序 294
10.2 實現二叉搜尋樹 297
10.3 從樹中刪除元素 303
10.4 合併任意樹 304
10.5 摺疊樹 310
10.5.1 用兩個函式摺疊 311
10.5.2 用一個函式摺疊 313
10.5.3 選擇哪種摺疊的實現 314
10.6 映射樹 316
10.7 平衡樹 317
10.7.1 旋轉樹 317
10.7.2 使用 DSW算法平衡樹 320
10.7.3 自動平衡樹 322
10.7.4 解決正確的問題 323
10.8 總結 324
第11章 用高級樹來解決真實問題 325
11.1 性能更好且棧安全的自平衡樹 326
11.1.1 樹的基本結構 326
11.1.2 往紅黑樹中插入元素 331
11.2 紅黑樹的用例:map 337
11.2.1 實現 map 337
11.2.2 擴展 map 340
11.2.3 使用鍵不可比較的 map 341
11.3 實現函式式優先佇列 344
11.3.1 優先佇列訪問協定 344
11.3.2 優先佇列使用案例 344
11.3.3 實現需求 345
11.3.4 左傾堆數據結構 345
11.3.5 實現左傾堆 346
11.3.6 實現像佇列一樣的接口 351
11.4 元素不可比較的優先佇列 352
11.5 總結 358
第12章 用函式式的方式處理狀態改變 359
12.1 一個函式式的隨機數發生器 360
12.1.1 隨機數發生器接口 361
12.1.2 實現隨機數發生器 362
12.2 處理狀態的通用API 366
12.2.1 使用狀態操作 367
12.2.2 複合狀態操作 368
12.2.3 遞歸狀態操作 370
12.3 通用狀態處理 372
12.3.1 狀態模式 374
12.3.2 構建一個狀態機 375
12.3.3 何時使用狀態和狀態機 381
12.4 總結 381
第13章 函式式輸入/輸出 382
13.1 在上下文中套用作用 383
13.1.1 作用是什麼 384
13.1.2 實現作用 384
13.1.3 用於失敗情況的更強大的作用 387
13.2 讀取數據 .390
13.2.1 從控制台讀取 390
13.2.2 從檔案中讀取 395
13.2.3 檢查輸入 396
13.3 真正的函式式輸入/輸出 398
13.3.1 怎樣才能讓輸入 /輸出是完全函式式的 398
13.3.2 實現純函式式的輸入 /輸出 399
13.3.3 合併 IO 400
13.3.4 用 IO處理輸入 402
13.3.5 擴展 IO類型 404
13.3.6 使 IO類型棧安全 407
13.4 總結 413
第14章 通過actor共享可變狀態 414
14.1 actor模型 .415
14.1.1 異步訊息 416
14.1.2 處理並行 416
14.1.3 處理 actor狀態變化 417
14.2 構建actor框架 418
14.2.1 actor框架的限制 418
14.2.2 設計 actor框架接口 418
14.2.3 AbstractActor的實現 420
14.3 開始使用actor 422
14.3.1 實現桌球示例 422
14.3.2 一個更嚴謹的例子:並行運行一個計算 424
14.3.3 重新排序結果 430
14.3.4 解決性能問題 433
14.4 總結 439
第15章 以函式式的方式解決常見問題 440
15.1 使用斷言來校驗數據 441
15.2 從檔案中讀取屬性 446
15.2.1 載入屬性檔案 446
15.2.2 將屬性讀取為字元串 447
15.2.3 生成更好的錯誤訊息 448
15.2.4 像列表那樣讀取屬性 451
15.2.5 讀取枚舉值 453
15.2.6 讀取任意類型的屬性 454
15.3 轉換命令式程式:XML讀取器 457
15.3.1 列出必需的函式 459
15.3.2 複合函式並套用作用 460
15.3.3 實現函式 461
15.3.4 讓程式更加函式式 462
15.3.5 修復參數類型問題 466
15.3.6 以處理元素的函式為參數 467
15.3.7 處理元素名稱錯誤 468
15.4 總結 470
附錄A 使用Java 8的函式式特性 471
附錄B Monad 479
附錄C 敢問路在何方 485