Java8的新特性,函数式编程和流式操作与Scala很相似。
函数式编程
OO(object oriented)是抽象数据,FP(functional programming)是抽象行为,函数式编程具有以下特点:
- 代码创建复用:通过合并现有代码来生成新功能而不是从头开始编写所有内容
- 并行编程,可靠性:不可变的变量,将值传递给函数,该函数然后生成新值但不修改自身外部的任何东西(包括其参数或该函数范围之外的元素)
语法糖
- lambda表达式:匿名函数,可以替代匿名内部类
(params) -> {function body}- 可指定参数类型:
(type param) -> {function body}
- 方法引用:
object::method,Class::method
函数接口
java.util.function包下提供了默认的函数接口@FunctionalInterface标记接口,编译器会检测该接口是否只有一个函数式方法(抽象方法),作为Lambda 表达式和方法引用的目标类型
常见接口
Predicate– 传入一个参数,返回一个bool结果。函数式方法为boolean test(T t);Consumer– 传入一个参数,无返回值。 函数式方法为void accept(T t);Function– 传入一个参数,返回一个结果。函数式方法为void accept(T t);BiFunction– 传入两个参数,类型不同。函数式方法为R apply(T t, U u);Supplier– 无参数传入,返回一个结果。函数式方法为T get();UnaryOperator– 一元操作符,继承Function,传入参数的类型和返回类型相同。函数式方法为T apply(T t);BinaryOperator– 二元操作符,继承BiFunction,传入的两个参数的类型和返回类型相同。函数式方法为T apply(T t, T u);
闭包
当函数使用了作用域之外的变量时,由函数及其相关的引用环境组合而成的实体就是闭包
- lambda表达式中引用了局部变量时,局部变量具有
final或者等同final效果 - lambda表达式中引用了对象的属性时,属性拥有独立生命周期,所以不需要强制
final修饰
public class Main {
int field;
// IntSupplier makeFun(final int x) {
IntSupplier makeFun(int x) {
// final int variable = 0;
int variable = 0;
// compile error
// return () -> x++ + variable++;
return () -> x + field++;
}
}
高阶函数
用于消费或者产生函数的函数
常见的组合函数就是高阶函数
andThen(argument):先执行调用者,再执行参数compose(argument):先执行参数,再执行调用者and(argument)or(argument)negate()
柯里化
将一个多参数的函数,转换为一系列单参数函数
// 柯里化函数
Function<String, Function<String, String>> sum =
a -> b -> a + b;
// 部分应用
Function<String, String> a = sum.apply("a")
// res: a1
a.apply("1")
// res: a2
a.apply("2")
流式编程
流是一系列与特定存储机制无关的元素。流可以使程序短小精悍,当应用 Lamda 表达式和方法引用时,更加地优雅。当使用parallel()时,可以将流分割为多个,并在不同处理器上分别执行操作,提升效率。
流创建
// 创建对象流,流中的元素都是对象
Stream.of(1, 2, 3);
Arrays.asList(1, 2, 3).stream();
// 创建数字流,流中的元素都是基本类型
IntStream.rangeClosed(1, 3);
IntStream.of(1, 2, 3);
IntStream ints = new Random().ints();
// 将数字流包装成对象流
ints.boxed();
// builder
IntStream.builder().add(1).add(2).build();
// iterate
Stream.iterate(1, i -> i + 1); // 1, f(1), f(f(1)), ...
// generate
Stream.generate(() -> 1); // 1, 1, 1, ...
中间操作
Peek:消费元素,但不改变流,适用于调试sorted(Comparator):排序distinct:去重filter(Predicate):过滤map(Function),mapToInt(Function),…:应用函数到元素flatMap(Function),flatMapToInt(Function),…:组合流skip(n):跳过limit(n):截断
终端操作
- 数组
toArraytoArray(generate)
- 循环
forEach(Consumer)forEachOrdered(Consumer):按原始流顺序迭代
- 集合
collect(Collector):由收集器收集流元素至集合中collect(Supplier, BiConsumer, Biconsumer):第一个参数 Supplier 创建了一个新结果集合,第二个参数 BiConsumer 将下一个元素包含到结果中,第三个参数 BiConsumer 用于将两个值组合起来
- 组合
reduce(BinaryOperator)reduce(T, BinaryOperator):T`为初始值
- 匹配
allMatch(Predicate):如果流的每个元素根据提供的Predicate都返回 true 时,结果返回为 true。在第一个 false 时,则停止执行计算。anyMatch(Predicate):如果流中的任意一个元素根据提供的Predicate返回 true 时,结果返回为 true。在第一个 false 是停止执行计算noneMatch(Predicate):如果流的每个元素根据提供的Predicate都返回 false 时,结果返回为 true。在第一个 true 时停止执行计算
- 查找
findFirst():返回第一个流元素的 Optional,如果流为空返回 Optional.emptyfindAny(:返回含有任意流元素的 Optional,如果流为空返回 Optional.empty
- 信息
- 对象流
count()max(Comparator)min(Comparator)
- 数字流
average()max()min()sum()
- 对象流
REFERENCE
[1] On Java8
文档信息
- 本文作者:wzx
- 本文链接:https://wzx140.github.io//2020/07/13/java8-FP/
- 版权声明:自由转载-非商用-非衍生-保持署名(创意共享3.0许可证)