lambda表达式
前言
lambda表达式是java8所引入的新特性之一,用于简化java中将某些功能传递给某些方法的功能举实现。将lambda当做一个变量,使得java能够写出函数式编程风格的代码。函数式编程风格在代码简洁性、可读性方面较原先的匿名类实现有很大的提升。
举个栗子-创建一个线程
- 匿名类实现:
new Thread(new Runnable() {
@Override
public void run() {
try {
System.out.println("running");
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
- lambda表达式实现:
new Thread(() -> {
try {
System.out.println("running");
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
通过上述栗子可见,使用lambda表达式具有比使用匿名类更简洁的代码编写风格。
那么lambda表达式,在java代码中是如何呈现的呢?本文将逐一展开介绍
1. lambda表达式结构
首先,顾名思义lambda表达式是一种没有声明方法的匿名函数表示形式,也就意味着该方法没有访问修饰符、返回值声明及方法名。
- lambda表达式结构:
(arg1…) -> { body }
- arg1 -> body ,body只有一条语句
- () -> { body }
- (arg1, arg2…) -> { body }
- (type1 arg1, type2 arg2…) -> { body }
- 双冒号( :: )结构
双冒号操作符在java中表示方法引用,可作为lambda调用特定方法的缩写,并且具有更好的可读性
目标引用::方法
- String::toString
- System.out::println
2. @FunctionalInterface注解
@FunctionalInterface注解是java8中新引入的一个注解,用于指示接口类型支持函数式编程风格接口。@FunctionalInterface会强制检查interface是否只有一个abstract方法,若interface存在多个abstract方法将会提升错误。
lambda表达式仅支持包含一个abstract方法的interface。
举个栗子–自定义一个函数编程风格的接口
- 普通接口写法
public interface Task <IN>{
void get(IN input);
}
- 使用@FunctionalInterface注解
@FunctionalInterface
public interface Task2 <IN>{
void get(IN input);
}
- 普通接口、@FunctionalInterface两种写法的单元测试及运行结果:
@SpringBootTest
@RunWith(SpringRunner.class)
public class Demo2Test {
@Test
public void taskTest() {
this.testTask(input -> {
System.out.println("hello, " + input);
}, "task");
this.testTask2(input -> {
System.out.println("hi, " + input);
}, "task2");
}
private <IN> void testTask(Task<IN> task, IN input) {
System.out.println("execute task");
task.execute(input);
}
public <IN> void testTask2(Task2<IN> task, IN input) {
System.out.println("execute task2");
task.execute(input);
}
}
执行结果:
execute task
hello, task
execute task2
hi, task2
上述两种方式的代码运行结果完全一样
- 使用@FunctionalInterface注解修饰包含两个及以上的abstract方法的interface,如下这个写法,代码编译不通过,IDE中代码检查会直接提升Multiple non-overriding abstract methods found in interface
@FunctionalInterface
public interface Task <IN, OUT>{
OUT get(IN input);
void get();
}
3 使用案例
lambda表达式在jdk8中有着丰富的使用案例,如流处理工具类Stream其中就大量的使用的lambda表达式。基本包含如下四种类型:
3.1 Supplier
只有返回值,没有入参
@FunctionalInterface
public interface Supplier<T> {
T get();
}
Stream中的list.stream().collect()方法的入参使用的就是Supplier类型。
3.2 Consumer
只有入参,没有返回值
@FunctionalInterface
public interface Consumer<T> {
void accept(T t);
}
Stream中的list.stream().forEach()方法的入参使用的就是Consumer类型。
3.3 Predicate
有入参,返回值是boolean类型
@FunctionalInterface
public interface Predicate<T> {
boolean test(T t);
}
Stream中的list.stream().filter()方法的入参使用的就是Predicate类型。
3.4 Funcation
既有入参、又有返回值
@FunctionalInterface
public interface Funcation<T, R> {
R accept(T t);
}
Stream中的list.stream().map()方法的入参使用的就是Funcation类型。