背景
JDK8开始引入的函数式编程,大大降低了Java编码的复杂度。它是一种编程范式,即一切都是数学函数。在Java中,函数式编程与lambda表达式密不可分。本文从最基础的编译原理的Statements && Expressions讲起,一步步带你深入浅出函数式编程。
一、Statements && Expressions
语句一般有表达式语句、声明语句、控制流语句,相当于自然语言中的一个句子,一个语句构成一个完整的执行单元。
表达式是由变量、运算符和方法调用组成的,这些变量、运算符和方法调用是根据语言的语法构造的,其计算结果为单个值。
Statements(语句) | Expressions(表达式) |
---|---|
执行某些操作 | 计算某个值 |
print("Hello World") | "Hello World" |
return 666; | 666 |
if (condition) {...} | condition |
表达式可以是语句的一部分,语句从来不是表达式的一部分;所有表达式都是有类型的。 尽管如此,不同的语言对于这些定义会略有不同。 既然提到了简单的提到了这些概念,那么Blocks一般由0或者多个statements组成,用Java示例如下,
代码语言:javascript复制public static void main(String[] args) {
boolean condition = true;
if (condition) { // begin block 1
System.out.println("Condition is true.");
} // end block one
else { // begin block 2
System.out.println("Condition is false.");
} // end block 2
}
二、Lambda与函数式编程
Lambda表达式(lambda expression)是一个匿名函数,Lambda表达式基于数学中的λ演算得名,直接对应于其中的lambda抽象(lambda abstraction),是一个匿名函数,即没有函数名的函数。
Java里,函数不是第一等公民,需要封装到接口里。 从而Java Lambda表达式 --> 内部匿名类。
函数式编程起源于称为函数理论的数学模型和 Lambda 演算中的 lambda。Lambda 表达式利用函数式编程特性。在 Java 中使用 Lambda 最明显的体验是它简化并减少了创建某些构造(例如匿名类)所需的源代码量。
lambda写法上一共两种,如下,经过上一章的铺垫这块大家看起来清晰了吧(手动狗头)。 (parameters) -> expressions 或 (parameters) -> { statements; } 代码示例一:
代码语言:javascript复制private static void lambda() {
IntSupplier integerExpression = () -> 5;
IntSupplier intSupplierStatement = () -> {
int a = 1;
int b = 1;
return a b;
};
}
代码实例二:
代码语言:javascript复制interface MyLambdaInterface {
void doSomeShit(String string);
}
public static void enact(MyLambdaInterface myLambdaInterface, String string) {
myLambdaInterface.doSomeShit(string);
}
private static void invoke() {
enact(string -> System.out.println(string), "Hello World");
}
三、常用的函数式接口
JDK 8 中提供了大量的函数式接口,这些接口定义在java.util.function中,因此我们一般情况下不需再定义自己的接口,同时,各个接口的作用和名字都是相对应的,所以,了解函数式接口的命名模式就是很有必要的了。
较为常见的就这四种,通过简单的代码调用,用法见文识义。
- Supplier->供应商
- Consumer->消费者
- Predicate->断言
- Function->函数
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
/**
* 常用的函数式接口
* Supplier->供应商
* Consumer->消费者
* Predicate->断言
* Function->函数
*
* @since 2021-10-22-10:04 AM
*/
class App {
public static void main(String[] args) {
// 无输入参数,返回T类型的一个结果。
// public interface Supplier<T>
Supplier<String> supplier = () -> "Test supplier";
supplier.get(); // return String | Test supplier
// 接受一个T类型的参数,无返回。
// public interface Consumer<T>
Consumer<String> consumer = (x) -> {
System.out.println(x);
};
// Consumer<String> consumer = System.out::println;
consumer.accept("Test consumer"); // void | 控制台打印 "Test consumer"
// 接受一个T类型的参数,返回布尔值。
// public interface Predicate<T>
Predicate<String> predicate = x -> x.contains("predicate");
predicate.test("Test predicate"); // return boolean | true
// 接受一个T类型的参数,返回R类型结果。
// public interface Function<T, R>
Function<Integer, String> function = x -> "This is Integer:" x;
function.apply(100); // return String | "This is Integer:100"
}
}
小结
Java作为一种通用编程语言,吸收了函数式范式,在函数式编程中,实现一个函数,该函数是不被包含在一个类中的,这也是面对对象和函数式编程的基本区别。
函数式编程语言里也可以有对象,但通常这些对象都是恒定不变的,一般是参数或者返回值。函数式编程语言里没有 for/next 循环,因为这些逻辑意味着有状态的改变。在函数式编程语言里通过递归、把函数当成参数传递的方式实现循环逻辑。