为什么要引入函数式编程
- 处理大型数据集合时,Java还欠缺高效的并行操作。
- 函数式编程能让程序员编写出更容易阅读的代码——这种代码更多地表达了业务逻辑的意图,而不是它的实现机制。易读的代码也易于维护、更可靠、更 不容易出错。面向对象编程是对数据进行抽象,而函数式编程是对行为进行抽象。
Lambda 表达式
What?
一种紧凑的、传递行为的方式。
How?
// no lambda
button.addActionListener(
new ActionListener() {
public void actionPerformed(ActionEvent event) {
System.out.println("button clicked");
}
});
// lambda
button.addActionListener(event -> System.out.println("button clicked"));
函数接口
使用只有一个方法的接口来表示某特定方法并反复使用,这种接口称为函数接口。(我的理解是这种接口只有一种行为,所以可以使用lambda表达式表示这个接口的具体行为。)
例如使用 Swing 编写过用户界面的人对这种方式都不陌生,代码如下
public interface ActionListener extends EventListener {
public void actionPerformed(ActionEvent event);
}
Java中重要的函数接口
接口 | 参数 | 返回类型 | 示例 |
---|---|---|---|
Predicate |
T | boolean | 这张唱片已经发行了吗 |
Consumer |
T | void | 输出一个值 |
Function<T,R> | T | R | 获得 Artist 对象的名字 |
Supplier |
None | T | 工厂方法 |
UnaryOperator |
T | T | 逻辑非(!) |
BinaryOperator |
(T,T) | T | 求两个数的乘积(*) |
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
/**
* author: zheng.hong
* date: 2020/10/29
* description: Java lambda 表达练习
*/
public class Java8Lamda {
public static void main(String[] args) {
//Function 接受一个入参T,返回R类型对象,使用apply方法获取方法执行的内容
Function<User, String> uft = u -> u.getUserName() ;
String userName = uft.apply(new User("mindong"));
System.out.println(userName);
//Consumer 接受一个参数T,没有返回值,使用accept方法对参数执行操作
Consumer<User> uc = u -> System.out.println(u.getUserName());
uc.accept(new User("liliang"));
//Supplier 没有入参,返回T类型结果,使用get方法获取返回结果
Supplier<User> us = () -> new User( "us");
User user = us.get();
//接受一个入参,返回结果为true或者false,使用test方法进行测试并返回测试结果
Predicate<User> predicate = u -> !u.getUserName().isEmpty();
System.out.println(predicate.test(user));
}
private static class User{
public User(String userName) {
this.userName = userName;
}
private String userName;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
}
}
Stream 流
常用的 Stream 流操作
collection(toList())
map
//对每个元素做平方运算
List<Integer> integers = Arrays.asList(1,2,3,4,5,6);
List<Integer> integers = Arrays.asList(1,2,3,4,5,6);
List<Integer> integers = integers.stream().map(number -> number*number).collect(Collectors.toList());
integers.forEach(number -> System.out.print(number+","));
filter
//过滤出偶数
List<Integer> integers = Arrays.asList(1,2,3,4,5,6);
integers = integers.stream().filter(number -> number%2 == 0).collect(Collectors.toList());
integers.forEach(number -> System.out.print(number+","));
flatMap
map 操作,它可用一个新的值代替 Stream 中的值。但有时,用户希望让 map 操作有点变化,生成一个新的 Stream 对象取而代之。
// 合并List
List<Integer> together = Stream.of(Arrays.asList(1, 2),Arrays.asList(3, 4)).flatMap(numbers -> numbers.stream())
.collect(Collectors.toList());
max 和min
//获取集合中最大值
List<Integer> integers = Arrays.asList(1,2,3,4,5,6);
Integer max = integers.stream().max(Comparator.comparing(Integer::intValue)).get();
System.out.println(max);
reduce
//求和
Integer sum = Stream.of(1,2,3).reduce(0,(sum,n)->sum+n );