归档后文章: 一文带你深入了解java和函数式编程
java对函数式的支持
java8提供了lambda表达式、方法引用、预定义函数接口来适配函数式编程。
java将lambda表达式看做函数式接口的对象实例,但这在设计层面上就已经满足一等值
的概念了。
函数式接口
jdk已经提供了一系列的函数式接口(Package java.util.function)了,例如Consumer、Supplier、Function、Predicate以及其他的出于拆箱装箱性能损耗的DoubleConsumer、IntPredicate,和基于多参数的BiConsumer等。
如果function
包下的接口还不能满足你的需求,可以配合桑除虫@FunctionalInterface
声明自己的函数式接口。对于函数式接口而言,@FunctionalInterface
其实是可加可不加的,它的作用是在编译时看看你的函数式接口
是否只有一个实例方法。
因为在java中,是通过实例化函数式接口的方式(常基于lambda表达式)来进行函数式支持的。
// 自定义消费int的函数式接口
@FunctionalInterface
interface consumeInt {
void consume(int i);
}
// 实例化函数式接口
consumeInt consumeInt = i -> System.out.println(i);
lambda表达式
lambda表达式的语法很简单:
(parameters) -> expression // 若只有一条执行语句的话不带{}
或
(parameters) ->{ statements; } // 多条执行语句带{},且带;
lambda表达式会自动推断参数的类型。一般来说是依赖于函数式接口指定的参数类型,但配合java范型的使用使lambda表达式拥有更为丰富的表达能力:
Function<String, String> function = str -> // 使用范型指定传入String 传出String
new StringBuilder(str).append("-").append(str.length()).toString();
// 当然也可以手动指定类型
Function<String, String> function = (String str)->...
方法引用
方法引用可以分为四类: 指向静态方法的、指向lambda表达式中变量的实例方法的、指向外部对象的实例方法的、构造函数的。
在java中方法的声明包括6个方面:修饰符、返回值、方法名、方法参数、异常列表、方法体。使用方法引用时:
- 修饰符要复合条件(访问不到的方法自然方法引用也不可用)
- 确保方法签名的匹配( 方法签名包含返回值和方法参数)
- 确保异常列表的兼容。(要求被引用的方法比需要的方法异常列表更小)
public class FunctionRefSt {
// 静态方法
public static int length(String str) {
return str.length();
}
// 实例方法
public int lengthIns(String str) {
return str.length();
}
// 四种引用的展示
@Test
public void funcRef() {
Optional<String> opt = Optional.of("hello world");
/*以下三种输出都是11*/
// 静态方法引用
opt.map(FunctionRefSt::length).ifPresent(System.out::println);
// 内部实例方法引用
opt.map(String::length).ifPresent(System.out::println);
// 外部实例方法引用
FunctionRefSt functionRefSt = new FunctionRefSt();
opt.map(functionRefSt::lengthIns).ifPresent(System.out::println);
/*构造函数引用实例*/
// 利用optional避免空指针
System.out.println(Optional.<List>ofNullable(null).orElseGet(/*引用了构造方法*/ArrayList::new).size());
//输出0
}
}
模式匹配
模式匹配
可以简单的理解成增强switch
表达式。java8目前还不支持模式匹配,其switch能支持的匹配类型还是比较少的: 枚举、String、byte、short、int、char以及一些基本类型的包装类
。在java12之后,switch表达式进行了一番的优化,jdk13switch特性:
// jdk12
switch (type) {
case "all" -> System.out.println("列出所有帖子");
case "auditing" -> System.out.println("列出审核中的帖子");
case "accepted" -> System.out.println("列出审核通过的帖子");
case "rejected" -> System.out.println("列出审核不通过的帖子");
default -> System.out.println("参数'type'错误,请检查");
}
// jdk13
String value = switch (i) {
case 0 -> "zero"
case 1 -> "one"
case 2 -> "two"
default -> "many"
};
System.out.println(value);