0.Java函数式编程
- 使用
函数式接口
、Lambda表达式
、Stream API
、方法引用
编写的代码即为函数式编程
1.函数式接口
- 只包含一个抽象方法
- 可以有默认方法
- 可以有静态方法
函数式接口(Functional Interface)是指仅包含一个抽象方法的接口。函数式接口是Java中支持函数式编程的关键概念之一。函数式编程强调的是将计算视为数学函数的求值,并避免程序状态的改变。Java 8引入了Lambda表达式和函数式接口的概念,以更方便地支持函数式编程。
函数式接口具有以下特点:
- 只包含一个抽象方法: 函数式接口只能包含一个抽象方法。这个抽象方法定义了接口的行为,而其他非抽象方法可以有多个。
- 可以有默认方法: 除了唯一的抽象方法外,函数式接口可以包含多个默认方法。默认方法在接口中已经有默认的实现,但仍然可以被子类覆盖。
- 可以有静态方法: 函数式接口还可以包含静态方法。这些方法在接口级别上是静态的,不依赖于接口的实例。
@FunctionalInterface //加上该注解,若接口不符合函数式接口的定义,编译器会产生错误interface MyInterface {//抽象方法int sum(int i, int j);//静态方法default int defaultSum(int i, int j){return i + j;}//默认方法static int staticSum(int i, int j){return i + j;}}
2.Lambda表达式
- 格式:(参数表) -> {方法体}
- Lambda表达式可简化函数式接口实例的创建
- 该格式实际为映射到函数式接口的抽象方法上
public static void main(String[] args) {//2.MyInterface的实现类实例,通过匿名内部类创建MyInterface myInterface = new MyInterface() {@Overridepublic int sum(int i, int j) {return i+j+1;}};//2.Lambda表达式简化函数式接口实例的创建//格式:(参数表) -> {方法体}//该格式实际为映射到函数式接口的抽象方法 sum()MyInterface myInterfaceLambda = (i, j) ->{return i+j+1;} ;System.out.println("myInterface.sum(3,4) = " + myInterface.sum(3, 4));System.out.println("myInterfaceLambda.sum(3,4) = " + myInterfaceLambda.sum(3, 4));}
3.Stream API
- Stream 是处理集合数据的工具,可以对数据集合进行各种转换、过滤、映射等操作
- 整个流程可以被概括为“创建 -> 中间操作 -> 终端操作”
- 在终端操作执行之前,中间操作是惰性的(通过回调执行),不会立即执行。
- 中间操作的方法参数为
回调函数
- 中甲操作和终端操作的执行顺序是交替执行的
public static void main(String[] args) {List<String> myList = Arrays.asList("5555", "1", "333", "22", "4444");myList.stream().filter(s -> {System.out.println("filter s = " + s); //【回调函数】if (s.length() < 3) {System.out.println("filter 收集到数据了");} else {System.out.println("filter 没有收集到数据了");}return s.length() < 3;}).map((Function<String, Object>) s -> {System.out.println("map s = " + s); //【回调函数】return s.toUpperCase();}).forEach(s -> {System.out.println("forEach s = " + s); //【回调函数】});}
Stream流中大量使用是函数式接口作为方法参数,因此,Lambda表达式在Stream流中大量使用
输出结果:
- 中间操作和终端操作是交替执行的
- 中间操作获取到一项数据后才会往后执行
filter s = 5555
filter 未收集到数据
filter s = 1
filter 收集到数据了!!!
map s = 1
forEach s = 1
filter s = 333
filter 未收集到数据
filter s = 22
filter 收集到数据了!!!
map s = 22
forEach s = 22
filter s = 4444
filter 未收集到数据
4.方法引用
简化Lambda表达式的编写,那么实质也是一个函数式接口
方法引用种类
- 静态方法引用
- 实例方法引用(无用,多此一举)
- 类方法引用
- 构造方法引用
//静态方法引用: 引用类的静态方法//格式:类名::静态方法// Lambda表达式Function<Integer, String> lambdaStatic = x -> Long.toString(x);// 静态方法引用Function<Integer, String> referenceStatic = Long::toString;//实例方法引用: 引用特定对象的实例方法//格式:实例::成员方法//和类方法引用的区别:目前来看,一个是无参函数,一个是有参函数。//实例方法引用应该很少用,多此一举的操作。可以直接用实例调用该方法就获取到结果,所以实例方法引用结果也是固定的,// Lambda表达式String str = "Hello";Supplier<Object> lambdaInstance = () -> str.toUpperCase();// 实例方法引用Supplier<String> referenceInstance = str::toUpperCase;//类方法引用:引用类的成员方法//格式:类名::成员方法// Lambda表达式Function<String, String> lambdaClass = s -> s.toUpperCase();// 类方法引用Function<String, String> referenceClass = String::toUpperCase;//构造方法引用: 引用类的构造方法。// Lambda表达式Supplier<List<String>> lambdaStructure = () -> new ArrayList<>();// 构造方法引用Supplier<List<String>> referenceStructure = ArrayList::new;
学习打卡:Java学习笔记-day04-Java函数式编程