《Java 8 函数式编程》笔记1

前记

在图书馆找有关 Java 的书时发现了这本动物出版社的书,大一时就听过 lambda,匿名函数之类的了(虽然两者不同),一直没机会接触前者,鉴于前段时间写的程序有好多匿名函数,很是冗余,本着好奇以及打算重构的心,就借来这本书打算学习一遍 lambda。本笔记按照章节顺序从第 2 章开始。

纸质书读起来很有滋味,建议买来或借来品味一番。

随书的资料在作者的 github 中可以下载到。

本笔记代码也全部放在 github 中,建议搭配代码食用~

设置断言

IdeaEclipse 都是默认不开启断言的,请先设置好。

lambda 表达式

第一行 lambda

使用匿名类将按钮和点击行为关联起来:

1
2
3
4
5
6
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent event) {
System.out.println("clicked");
}
});

使用 lambda 表达式:

1
button.addActionListener(event -> System.out.println("clicked"));

匿名类:

  • 方法参数类型需要显式声明:ActionEvent event

lambda:

  • 无需指定类型,javac 根据上下文推断出 event 的类型(addActionListener 方法的签名)

注:

  1. lambda 声明参数时也可以包括参数类型(比如:(int x, int y) -> x + y);
  2. 有时编译器不一定能根据上下文推断出参数类型,这时要显示声明。

lambda 表达式的不同形式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 该 Runnable 接口只有 1 个 void run() 方法
// 使用空括号 () 表示没有参数
Runnable noArguments = () -> System.out.println("Hello");

// 只有 1 个参数,可省略括号
ActionListener oneArgument = event -> System.out.println("clicked");

// lambda 主体不仅可以是表达式,也可以是一段代码块
// 用大括号 {} 括起来的代码块
// 遵循的规则和普通方法一样
Runnable multiStatement = () -> {
System.out.println("Hello 1");
System.out.println("Hello 2");
};

// 显式声明参数类型
BinaryOperator<Integer> addExplicitType = (Integer x, Integer y) -> x + y;

// 这段代码是创建一个函数,用来计算出两个数字相加的结果
// add 不是两个数字的和,而是将两个数字相加的那行代码
BinaryOperator<Integer> add = (x, y) -> x + y;
System.out.println(add.apply(1, 2));

引用值,而不是变量

匿名类中使用所在方法的变量时需要 final 修饰:

1
2
3
4
5
6
7
8
final String username = getUsername();

button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent event) {
System.out.println(username + " clicked");
}
});

lambda 表达式中使用时虽然可以没有 final 修饰符,但实际上仍是 final 变量:

1
2
3
String username = getUsername();

button.addActionListener(event -> System.out.println(username + " clicked"));

使用 final 变量,实际上就是使用赋给该变量的一个特定值。

函数接口

函数接口:只有 1 个抽象方法的接口,用作 lambda 表达式的类型。

比如 ActionListener 接口:

1
2
3
public abstract ActionListener extends EventListener {
public abstract void actionPerformed(ActionEvent event);
}

该单一抽象方法的命名并不重要,只要方法签名和 lambda 表达式的类型匹配即可。

一些最重要的函数接口:

接口参数返回类型示例
PredicateTboolean这张唱片发行了吗
ConsumerTvoid输出一个值
Function<T, R>TR获得 A 对象的名字
SupplierNoneT工厂方法
UnaryOperatorTT逻辑非(!)
BinaryOperator(T,T)T求两个数的和(+)
Author

Zoctan

Posted on

2018-03-05

Updated on

2023-03-14

Licensed under