JDK8 之 Lambda 总结
文章目录
一. 简介
Lambda 是一个匿名函数,我们可以把 Lambda 表达式理解为是一段可以传递的代码(将代码 像数据一样进行传递)。可以写出更简洁、更 灵活的代码。作为一种更紧凑的代码风格,使 Java的语言表达能力得到了提升.
二. 使用效果
2.1 未使用 lambda 和 使用 lambda 的区别
/**
* 未使用 lambda 表达式
*/
@Test
public void test01() {
Comparator<Integer> comparator1 = new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return Integer.compare(o1,o2);
}
};
TreeSet set = new TreeSet(comparator1);
}
/**
* 使用 lambda 表达式
*/
@Test
public void test02() {
// 使用 lambda
Comparator<Integer> comparator = (o1,o2) -> Integer.compare(o1,o2);
TreeSet set = new TreeSet(comparator);
}
三. 基本语法
Lambda 表达式在Java 语言中引入了一个新的语法元 素和操作符。这个操作符为 “->” , 该操作符被称 为 Lambda 操作符或剪头操作符。它将 Lambda 分为 两个部分:
左侧:指定了 Lambda 表达式需要的所有参数
右侧:指定了 Lambda 体,即 Lambda 表达式要执行 的功能。
// 语法格式一: 无参, 无返回值, lambda 体只需要执行一条语句
Runnable runnable = () -> System.out.println("hello world");
// 语法格式二: 有一个参数, 并且无返回值
Consumer<String> consumer = (args) -> System.out.println(args);
// 语法格式三: 只有一个参数时,参数的小括号可以省略
Consumer<String> consumer2 = args -> System.out.println(args);
// 语法格式四: lambda 需要两个参数,多行执行语句,并且有返回值
Comparator<Integer> comparator = (a, b) -> {
System.out.println("hello world");
return Integer.compare(a, b);
};
// 语法格式五: lambda 需要两个参数,一条执行语句,并且有返回值
Comparator<Integer> comparator2 = (a, b) -> Integer.compare(a, b);
// 语法格式六: lambda 表达式的参数列表的数据类型可以省略不写,因为 jvm 编译器可以通过上下文推断出数据类型,即"类型推断"
Comparator<Integer> comparator3 = (Integer a, Integer b) -> Integer.compare(a, b);
四. 函数式接口
- 只包含一个抽象方法的接口,称为函数式接口。
- 你可以通过 Lambda 表达式来创建该接口的对象。(若 Lambda
表达式抛出一个受检异常,那么该异常需要在目标接口的抽象方
法上进行声明)。 - 我们可以在任意函数式接口上使用 @FunctionalInterface 注解,
这样做可以检查它是否是一个函数式接口,同时 javadoc 也会包含一条声明,说明这个接口是一个函数式接口。
Lambda 表达式需要"函数式接口"的支持
一个抽象方法不会报错.
两个抽象方法编译报错.
五.内置四大核心函数式接口
5.1 Consumer
消费型函数接口
源码:
@FunctionalInterface
public interface Consumer<T> {
void accept(T t);
}
Demo:
5.2 Supplier
供给型函数接口
源码:
@FunctionalInterface
public interface Supplier<T> {
T get();
}
Demo:
5.3 Function<T, R>
函数型函数接口
源码:
@FunctionalInterface
public interface Function<T, R> {
R apply(T t);
}
Demo:
5.4 Predicate
断言型函数接口
源码:
@FunctionalInterface
public interface Predicate<T> {
boolean test(T t);
}
Demo:
六. 其他函数式接口
学会了内置四大核心函数式接口,在学习其他的就比较简单了.具体的可以自己查看源码,看看接口中的唯一方法是什么.
部分:
全部:
七. 方法引用
当要传递给 Lambda 体的操作,已经有实现的方法了,可以使用方法引用! (实现抽象方法的参数列表,必须与方法引用方法的参数列表保持一致!) 方法引用:使用操作符 “::” 将方法名和对象或类的名字分隔开来。 如下三种主要使用情况:
- 对象::实例方法
- 类::静态方法
- 类::实例方法
7.1 类::静态方法名
类为:
Integer
静态方法名:compare
简单示例:
源码:
/**
* 类::静态方法名
*/
@Test
public void test09() {
// 例如:创建比较器
Comparator<Integer> comparator1 = (o1, o2) -> Integer.compare(o1, o2);
// 等同于
Comparator<Integer> comparator2 = Integer::compare;
System.out.println(comparator1.compare(1, 2));
System.out.println(comparator2.compare(1, 2));
}
7.2 对象::实例方法名
对象:
PrintStream
静态方法名:println
简单示例:
源码:
/**
* 对象::实例方法名
*/
@Test
public void test13() {
// 例如:这个函数是打印传入的 name 值
Consumer<String> consumer1 = (name) -> System.out.println(name);
// 创建对象
PrintStream ps = System.out;
// 等同于
Consumer<String> consumer2 = ps::println;
consumer1.accept("zcsh1");
consumer1.accept("zcsh2");
}
7.3 类::实例方法名
类:
String
实例方法名:equals
简单实例:
八. 构造器引用
格式:
ClassName::new
与函数式接口相结合,自动与函数式接口中方法兼容。 可以把构造器引用赋值给定义的方法,与构造器参数 列表要与接口中抽象方法的参数列表一致!
8.1 无参构造器引用
简单示例:
源码:
private class Employee {
private String name = "zcsh";
}
/**
* 无参构造器引用
*/
@Test
public void test12() {
// 例如创建一个初始的 employee 对象
Supplier<Employee> supplier1 = () -> new Employee();
// 等同于
Supplier<Employee> supplier2 = Employee::new;
System.out.println(supplier1.get().name);
System.out.println(supplier2.get().name);
}
8.2 无参构造器
简单示例:
源码:
private class Employee2 {
private String name = "zcsh";
public Employee2(String name) {
this.name = name;
}
}
/**
* 有参构造器引用
*/
@Test
public void test13() {
// 例如创建一个初始的 employee 对象
Function<String, Employee2> function1 = (name) -> new Employee2(name);
// 等同于
Function<String, Employee2> function2 = Employee2::new;
System.out.println(function1.apply("zcsh1").name);
System.out.println(function2.apply("zcsh2").name);
}
8.3 数组引用
简单示例:
源码:
/**
* 数组引用
*/
@Test
public void test14() {
// 创建一个长度为 length 的数组
Function<Integer,Integer[]> function1 = (length) -> new Integer[length];
// 等同于
Function<Integer,Integer[]> function2 = Integer[]::new;
System.out.println(function1.apply(10).length);
System.out.println(function2.apply(10).length);
}