JDK8函数式编程
1、概述
为什么需要学?
因为Java的发展在进步,就比如说可以简化代码,一些for循环里面你还有套娃,写出来的代码就显得非常厚重,其次就是ES(ElasticSearch)、reactive(响应式)等等,都用到了函数式编程,所以有什么理由不学呢?
2、lambda表达式
2.1 概述
百度百科:Lambda 表达式(lambda expression)是一个匿名函数,Lambda表达式基于数学中的λ演算得名,直接对应于其中的lambda抽象(lambda abstraction),是一个匿名函数,即没有函数名的函数。Lambda表达式可以表示闭包(注意和数学传统意义上的不同)。
Java 8的一个大亮点是引入Lambda表达式,使用它设计的代码会更加简洁。当开发者在编写Lambda表达式时,也会随之被编译成一个函数式接口。下面这个例子就是使用Lambda语法来代替匿名的内部类,代码不仅简洁,而且还可读。
2.2 基本格式
(参数列表)-> {代码}
举栗子:
例一:
我们在创建线程的重写run方法并调用是这样的:
// 当想看方法或者对象里面的参数可以 ctrl + p
new Thread(new Runnable() {
public void run() {
System.out.println(Thread.currentThread().getName()+"线程调用");
}
},"A").start();
当我们使用lambda表达式后:
new Thread(()->{
System.out.println(Thread.currentThread().getName()+"线程调用");
},"A").start();
例二:
有一个方法,参数是一个接口:
public static int calculateNum(IntBinaryOperator operator) {
int a = 10;
int b = 20;
return operator.applyAsInt(a, b);
}
我们进行调用,先用匿名内部类进行调用:
// 将鼠标放到接口按 alt+enter 可以来回切换匿名内部类和lambda表达式
calculateNum(new IntBinaryOperator() {
@Override
public int applyAsInt(int left, int right) {
return 0;
}
});
转为lambda表达式:
calculateNum((int left, int right) -> {
return left + right;
});
例三:
public static void printNum(IntPredicate predicate){
int[] arr = {1,2,3,4,5,6,7,8,9,10};
for (int i : arr) {
if (predicate.test(i)){
System.out.print(i+" ");
}
}
}
使用匿名内部类进行调用
printNum(new IntPredicate() {
@Override
public boolean test(int value) {
return value%2 == 0;
}
});
使用lambda表达式:
printNum((int value)->{
return value%2 ==0;
});
例四:
这里有一个方法,参数是函数式接口
public static <R>R typeCover(Function<String,R> function){
String str = "1235";
R result = function.apply(str);
return result;
}
新手写这种方法一定要先写匿名内部类,便于理解
Integer i = typeCover(new Function<String, Integer>() {
@Override
public Integer apply(String s) {
return Integer.parseInt(s);
}
});
String str = typeCover(new Function<String, String>() {
@Override
public String apply(String s) {
return s+"ywj";
}
});
转为lambda表达式:
typeCover((String s)->{
return Integer.parseInt(s);
});
str = typeCover((String s)->{
return s+"yjw";
});
例五:
public static void foreachArr(IntConsumer consumer){
int[] arr = {1,2,3,4,5,6,7,8,9,10};
for (int i : arr) {
consumer.accept(i);
}
}
匿名内部类:
foreachArr(new IntConsumer() {
@Override
public void accept(int value) {
System.out.println(value);
}
});
lambda表达式:
foreachArr((int value)->{
System.out.println(value);
});
2.3省略规则:
- 参数类型可以省略
- 方法体只有一句话时大括号return和唯一一句代码的分号可以省略
- 方法只有一个参数时小括号可以省略
2.4总结
- 在使用lambda表达式之前尽量先使用匿名内部类的方式,这样可以更好地理解
- lambda表达式,无非就是去掉接口名,方法名,我们只需要关心参数列表和方法体
- 简化代码,有一些没必要写的就可以去掉,比如:数据类型、括号等等
- 最终技巧:懒人技巧,先使用匿名内部类创建,然后选中参数中的接口名,直接使用idea快捷键 alt+enter 自动创建lambda表达式