一、Lambda表达式
Lambda 是一个匿名函数,我们可以把 Lambda表达式理解为是一段可以传递的代码(将代码像数据一样进行传递)。可以写出更简洁、更灵活的代码。作为一种更紧凑的代码风格,使Java的语言表达能力得到了提升
1、举例
( o1 , o2 ) -> Integer.compare( o1 , o2 )
2、格式
- -> : lambda 操作符或箭头操作符
- -> 左边 :lambda 形参列表(其实就是抽象中的抽象方法的形参列表)
- -> 右边 :lambda 体(其实就是重写的抽象方法的方法体)
3、lambda 表达式的使用(6种情况)
Runnable r = () -> System.out.println("hello");
Consumer<String> consumer = (args) -> System.out.println(args);
Consumer<String> consumer2 = args -> System.out.println(args);
BinaryOperator<Long> bo = (Long x,Long y) -> {
System.out.println("实现函数接口方法!");
return x + y;
};
BinaryOperator<Long> bio = (Long x,Long y) -> x + y;
BinaryOperator<Long> bio = (x, y) -> x + y;
4、lambda 表达式的本质:作为接口的实例
二、函数式接口
1、什么是函数式接口
- 只包含一个抽象方法的接口,称为函数式接口。
- 你可以通过 Lambda 表达式来创建该接口的对象。(若 Lambda 表达式抛出一个受检异常,那么该异常需要在目标接口的抽象方法上进行声明)。
- 我们可以在任意函数式接口上使用 @FunctionalInterface 注解,这样做可以检查它是否是一个函数式接口,同时 javadoc 也会包含一条声明,说明这个接口是一个函数式接口。
2、自定义函数式接口
@FunctionalInterface
public interface MyInterface {
public String getValue();
}
@FunctionalInterface
public interface MyInterface<T> {
public T getValue(T t);
}
3、Lambda 表达式作为参数传递
注意:为了将 Lambda 表达式作为参数传递,接收Lambda 表达式的参数类型必须是与该 Lambda 表达式兼容的函数式接口的类型。
4、Java 内置四大核心函数式接口
消费型接口Consumer
void accept(T t)
@Test
public void testConsumer() {
// 消费型接口Consumer<T> void accept(T t)
buyCar(265000.00, new Consumer<Double>() {
@Override
public void accept(Double aDouble) {
System.out.println("买车花费了:" + aDouble);
}
});
System.out.println("使用lambda表达式如下");
buyCar(99999.99, money -> System.out.println("买车花费了:" + money));
}
/**
* 利用Consumer 实现消费
* @param money 金额
* @param con 所消费金额
*/
public void buyCar(Double money, Consumer<Double> con) {
con.accept(money);
}
断定型接口Predicate
boolean test(T t)
@Test
public void testPredicate() {
// 断定型接口Predicate<T> boolean test(T t)
List<String> list = Arrays.asList("aabb", "bbcc", "ccdd", "aadd");
List<String> res = filterString(list, new Predicate<String>() {
@Override
public boolean test(String s) {
return s.contains("aa");
}
});
System.out.println("过滤后:" + res);
System.out.println("使用lambda表达式如下");
List<String> res2 = filterString(list, s -> s.contains("aa"));
System.out.println("过滤后:" + res2);
}
/**
* 利用Predicate 实现过滤
* @param list 原数组
* @param pre 约束条件
* @return 过滤后数组
*/
public List<String> filterString(List<String> list, Predicate<String> pre) {
List<String> result = new ArrayList<>();
for (String s : list) {
if (pre.test(s)) {
result.add(s);
}
}
return result;
}
供给型接口Supplier
T get()
函数型接口Function<T,R> R apply(T t)
5、其他接口
三、函数式引用(方法引用与构造器引用)
使用场景
当要传递给 Lambda 体的操作,已经有实现的方法了,可以使用方法引用!
方法引用,本质上也是 Lambda 表达式,而 Lambda 表达式作为函数式接口的实例。所以,方法引用也是函数式接口的实例。
使用格式
方法引用使用的要求:要求接口中的抽象方法的形参列表和返回值类型与方法引用的方法的形参列表和返回值类型相同!(情况三特殊)
情况一 对象 :: 非静态方法
情况二 类 :: 静态方法
情况三 类 :: 非静态方法
示例代码
package com.mv.java8.basic;
import org.junit.Test;
import java.io.PrintStream;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Date;
import java.util.funct