mirror of
https://github.com/LingCoder/OnJava8.git
synced 2026-08-24 15:03:29 +08:00
更新第十三章目录子标题
This commit is contained in:
18
SUMMARY.md
18
SUMMARY.md
@@ -161,15 +161,15 @@
|
||||
* [for-in和迭代器](book/12-Collections.md#for-in和迭代器)
|
||||
* [本章小结](book/12-Collections.md#本章小结)
|
||||
* [第十三章 函数式编程](book/13-Functional-Programming.md)
|
||||
* [](book/13-Functional-Programming.md#)
|
||||
* [](book/13-Functional-Programming.md#)
|
||||
* [](book/13-Functional-Programming.md#)
|
||||
* [](book/13-Functional-Programming.md#)
|
||||
* [](book/13-Functional-Programming.md#)
|
||||
* [](book/13-Functional-Programming.md#)
|
||||
* [](book/13-Functional-Programming.md#)
|
||||
* [](book/13-Functional-Programming.md#)
|
||||
* [](book/13-Functional-Programming.md#)
|
||||
* [旧vs新](book/13-Functional-Programming.md#旧vs新)
|
||||
* [Lambda表达式](book/13-Functional-Programming.md#Lambda表达式)
|
||||
* [方法引用](book/13-Functional-Programming.md#方法引用)
|
||||
* [函数式接口](book/13-Functional-Programming.md#函数式接口)
|
||||
* [高阶函数](book/13-Functional-Programming.md#高阶函数)
|
||||
* [闭包](book/13-Functional-Programming.md#闭包)
|
||||
* [函数组合](book/13-Functional-Programming.md#函数组合)
|
||||
* [Currying和Partial-Evaluation](book/13-Functional-Programming.md#Currying和Partial-Evaluation)
|
||||
* [纯函数式编程](book/13-Functional-Programming.md#纯函数式编程)
|
||||
* [本章小结](book/13-Functional-Programming.md#本章小结)
|
||||
* [第十四章 流式编程](book/14-Streams.md)
|
||||
* [](book/14-Streams.md#)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
[TOC]
|
||||
|
||||
# 第十三章-函数式编程
|
||||
<!-- Functional Programming -->
|
||||
# 第十三章 函数式编程
|
||||
|
||||
|
||||
|
||||
@@ -28,9 +29,10 @@ OO (object oriented) 是抽象数据,FP (functional programming) 是抽象行
|
||||
|
||||
FP的想法值得融入非FP语言。 例如,这种情况发生在Python语言中。 Java 8在FP中添加了自己的功能,我们将在此章探讨。
|
||||
|
||||
<!-- Old vs. New -->
|
||||
|
||||
## 旧 VS 新
|
||||
<!-- Old vs. New -->
|
||||
## 旧vs新
|
||||
|
||||
|
||||
通常,方法会根据我们传递的数据产生不同的结果。 如果您希望某个方法在从一个调用到下一个调用时表现不同,该怎么办? 如果我们将代码传递给方法,我们可以控制它的行为。 以前,我们通过在方法中创建包含所需行为的对象,然后将该对象传递给我们想要控制的方法来完成此操作。 以下示例显示了这一点,然后添加了 Java 8方法:方法引用和 lambda 表达式。
|
||||
|
||||
@@ -110,7 +112,10 @@ Hello there Hello there
|
||||
|
||||
在Java 8之前,我们已经能够通过[1]和[2]传递功能。但是,写入和读取的语法非常笨拙,我们只在强制时才这样做。 方法引用和lambda表达式可以在您需要时传递功能,而不是仅在必要时传递功能。
|
||||
|
||||
## Lambda 表达式
|
||||
|
||||
<!-- Lambda Expressions -->
|
||||
## Lambda表达式
|
||||
|
||||
|
||||
Lambda表达式是使用最小可能语法编写的函数定义:
|
||||
|
||||
@@ -273,9 +278,9 @@ public class RecursiveFibonacci {
|
||||
将Fibonacci 序列对中的最后两个元素求和来产生下一个元素。
|
||||
|
||||
<!-- method references-->
|
||||
|
||||
## 方法引用
|
||||
|
||||
|
||||
Java 8 方法引用指的是没有以前版本的 Java 所需的额外包袱的方法。 方法引用是类名或对象名,后面跟 :: [^4],然后是方法的名称。
|
||||
|
||||
```java
|
||||
@@ -523,8 +528,10 @@ public class CtorReference {
|
||||
|
||||
编译器可以看到调用函数方法( 在本例中为make())意味着调用构造函数。
|
||||
|
||||
<!-- Functional Interfaces -->
|
||||
## 函数式接口
|
||||
|
||||
|
||||
方法引用和lambda表达式都是必须赋值的,并且这些赋值需要编译器的类型信息以确保类型正确性。 Lambda表达式特别引入了新的要求。 考虑:
|
||||
|
||||
```java
|
||||
@@ -889,9 +896,9 @@ public interface IntToDoubleFunction {
|
||||
当然,如果由于缺少原始类型的函数而导致性能实际上成为问题,您可以轻松编写自己的接口( 使用Java库源进行参考 ) - 尽管这似乎不太可能是您的性能瓶颈。
|
||||
|
||||
<!-- Higher-Order Functions-->
|
||||
|
||||
## 高阶函数
|
||||
|
||||
|
||||
这个名字听起来有点令人生畏,但是:高阶函数只是一个消耗或产生函数的函数。
|
||||
|
||||
我们先来看看产生一个函数:
|
||||
@@ -984,8 +991,10 @@ O
|
||||
|
||||
在这里,**transform()**生成一个与传入的函数具有相同签名的函数,但是您可以生成任何您想要的类型。这在 **Function** 接口中使用名为 **andThen()**的默认方法,该方法专门用于操作函数。 顾名思义,在调用in函数之后调用 **toThen()**(还有 **compose()**,它在 **in** 函数之前应用新函数)。 要附加一个**andThen()**函数,我们只需将该函数作为参数传递。 **transform()**产生的是一个新函数,它将 **in** 的动作与 **andThen()**参数的动作结合起来。
|
||||
|
||||
<!-- Closures -->
|
||||
## 闭包
|
||||
|
||||
|
||||
在上一节的 **ProduceFunction.java** 中,我们从方法返回了一个 lambda 函数。 这个例子让事情变得简单,但是我们必须在返回 lambdas 时探讨一些问题。
|
||||
|
||||
*闭包*一词概括了这些问题。 闭包非常重要,因为它们可以轻松生成函数。
|
||||
@@ -1236,9 +1245,9 @@ public class AnonymousClosure {
|
||||
事实证明,只要有内部类,就会有闭包(Java 8只 会使闭包变得更容易)。 在 Java 8 之前,要求是 **x** 和 **i** 被明确声明为 **final**。 使用 Java 8,内部类的规则已经放宽,包括 “effectively final”。
|
||||
|
||||
<!-- Function Composition -->
|
||||
|
||||
## 函数组合
|
||||
|
||||
|
||||
函数组合基本上意味着“将函数粘贴在一起以创建新函数”,它通常被认为是函数编程的一部分。您在**TransformFunction.java** 中看到了一个使用 **andThen()** 的函数组合示例。一些 **java.util** 的函数接口包含支持函数组合的方法。
|
||||
|
||||
Compositional Supporting Method Interfaces Function BiFunction Consumer BiConsumer IntConsumer andThen(argument) Performs the original LongConsumer operation followed by DoubleConsumer the argument operation.
|
||||
@@ -1309,8 +1318,8 @@ foobaz
|
||||
你可以从输出中看到 **p4** 是如何工作的:任何带有 “foo ”的东西都会存活,即使它的长度大于5。 “fongopuckey” 太长了,没有 “bar” 来保存它。
|
||||
|
||||
<!-- Currying and Partial Evaluation -->
|
||||
## Currying和Partial-Evaluation
|
||||
|
||||
## Currying 和 Partial Evaluation
|
||||
|
||||
*Currying* 以 Haskell Curry 命名,Haskell Curry 是其发明者之一,可能是唯一一个以他的名字命名的重要事物的计算机领域的人物(另一个是 Haskell 编程语言)。 Currying 意味着从一个函数开始,该函数接受多个参数,并将其转换为一系列函数,每个函数只接受一个参数。
|
||||
|
||||
@@ -1405,14 +1414,16 @@ public class CurriedIntAdd {
|
||||
您可以在因特网上找到更多 currying 示例。 通常这些是 Java 以外的语言,但如果你理解它们的基本概念,它们应该很容易翻译。
|
||||
|
||||
<!-- Pure Functional Programming -->
|
||||
|
||||
## 纯函数式编程
|
||||
|
||||
|
||||
在没有函数支持的情况下,即使用像C这样的原始语言,也可以按照一定的原则编写纯函数程序。Java使它比这更容易,但是您必须小心地使一切都成为 **final**,并确保您的所有方法和函数没有副作用。因为 Java 本质上不是一种不可变的语言,所以如果您犯了错误,编译器不会提供任何帮助。
|
||||
|
||||
有第三方工具可以帮助您[^9],但是使用 **Scala** 或 **Clojure** 这样的语言可能更容易,因为它们从一开始就是为保持不变性而设计的。这些语言使您可以用 Java 编写项目的一部分,如果您必须用纯函数式编写,则可以用**Scala** 编写其他部分 (这需要一些规则) 或 **Clojure** (这需要的少得多)。虽然您将在并发编程一章中看到 Java确实支持并发,但是如果这是您项目的核心部分,您可能会考虑至少在项目的一部分中使用 **Scala** 或 **Clojure**之类的语言。
|
||||
|
||||
## 总结
|
||||
<!-- Summary -->
|
||||
## 本章小结
|
||||
|
||||
|
||||
Lambda 表达式和方法引用并没有将 Java 转换成函数式语言,而是提供了对函数式编程的支持。它们对 Java 是一个巨大的改进,因为它们允许您编写更简洁、更干净、更容易理解的代码。在下一章中,您将看到它们如何启用流。如果你像我一样,你会喜欢流媒体。
|
||||
|
||||
|
||||
Reference in New Issue
Block a user