什么是lambda ? 解决什么问题?
要知道lambda 表达式,首先要先了解函数式接口
。
函数式接口,就是一个接口只提供一个方法(但可以有多个默认方法),并可以再接口上方用@FunctionalInterface
来标记。如下:
@FunctionalInterface
public interface Function<T, R> {
R apply(T t);
}
这里的接口,我们能明确它的入参类型,出参类型,处理逻辑由具体的实现类来实现。所以我们所关注的其实只有方法实现本生。lambda 是指是匿名内部类,省略了一大堆不必要的元素,只保留了入参,出参,处理逻辑。具体结构参考 lambda 表达式的结构
。
lambda 是行为参数化
的一种重要表现方式。
解决问题:针对多变的需求,接口作为参数传递是比较好的解耦方式;极大的简化代码。
lambda 表达式的结构
(x,y)-> x + y // (parameters) -> expression 或 (parameters) -> { statements; }
parameters:(x,y) 此部分是 参数列表
参数2:-> 箭头
参数3:lambda 表达式主体,可以是简单的一个表达式,也可以是复杂的多个表达式。多个表达式要带 {}
与 ;
。
lambda 应用场景
接口参数化,我们来看一个 java 8 in action
中的例子。
public static String processFile() throws IOException{
try(BufferedReader br = new BufferedReader(new FileReader("data.txt"))){
return br.readLine();
}
}
//定义函数式接口
@FunctionalInterface
public interface BufferedReaderProcessor{
String process(BufferedReader b) throws IOException;
}
//入参接口
public static String processFile(BufferedReaderProcessor p) throws IOException{
try(BufferedReader br = new BufferedReader(new FileReader("data.txt"))){
return p.process(br);
}
}
//方法调用,行为参数
String online = processFile((BufferedReader br)->br.readLine());
JDK 自带的几个常用函数式接口,在后面的 stream
等很多地方都有使用。
//有返回值
@FunctionalInterface
public interface Function<T, R> {
R apply(T t);
}
//无返回值
@FunctionalInterface
public interface Consumer<T> {
void accept(T t);
}
//返回 boolean 类型
@FunctionalInterface
public interface Predicate<T> {
boolean test(T t);
}
除此之后,JDK 中还定义了很多这三类的变形函数式接口。当然,我们自己也可以定义自己的函数式接口。
类型检查、类型推断与限制
类型检查,根据接口定义时指定泛型进行检查。
类型推断,根据接口定义指定泛型进行推断。如:
public class Apple {
private String color;
private int weight;
//getter,setter
}
//接口定义如下
@FunctionalInterface
public interface Comparator<T> {
int compare(T o1, T o2);
}
//lambda 表达式。此时泛型T 指代的是 Apple
Comparator<Apple> a = (a, b) -> a.getColor().compareTo(b.getColor());
复合lambda表达式使用
所谓复合,即通过接口提供多个default
方法,进行多重操作。Comparator (比较器复合)、 Function(函数复合) 和 Predicate (谓词复合)都有各自的复合操作。
例如,Comparator :sort, reversed, thenComparing
//Comparator 按重量递减排序
inventory.sort(comparing(Apple::getWeight).reversed());
//Comparator 比较链
inventory.sort(comparing(Apple::getWeight)
.reversed()
.thenComparing(Apple::getCountry));
Predicate:
//Predicate negate
Predicate<Apple> notRedApple = redApple.negate();
//Predicate and
Predicate<Apple> redAndHeavyApple =
redApple.and(a -> a.getWeight() > 150);
//Predicate and 和 or
Predicate<Apple> redAndHeavyAppleOrGreen =
redApple.and(a -> a.getWeight() > 150)
.or(a -> "green".equals(a.getColor()));
Function: andThen 和 compose 表示 f(g(x))
Function<Integer, Integer> f = x -> x + 1;
Function<Integer, Integer> g = x -> x * 2;
Function<Integer, Integer> h = f.andThen(g);
int result = h.apply(1);
//或者 注意f 与 g 的先后顺序
Function<Integer, Integer> f = x -> x + 1;
Function<Integer, Integer> g = x -> x * 2;
Function<Integer, Integer> h = f.compose(g);
int result = h.apply(1);
常见案例
说明:案例中的所有实体 Apple 如下:
@Data
public class Apple {
private String color;
private int weight;
}
Predicate:
public class Predicate {
public static List<Apple> filter(List<Apple> apples, Predicate<Apple> predicate) {
List<Apple> result = new ArrayList<>();
for (Apple apple : apples) {
if (predicate.test(apple))
result.add(apple);
}
return result;
}
public static List<Apple> filter2(List<Apple> apples, IntPredicate intPredicate) {
List<Apple> result = new ArrayList<>();
for (Apple apple : apples) {
if (intPredicate.test(apple.getWeight()))
result.add(apple);
}
return result;
}
public static List<Apple> colorAndWeightFilter(List<Apple> apples, BiPredicate<String, Integer> biPredicate) {
List<Apple> result = new ArrayList<>();
for (Apple apple : apples) {
if (biPredicate.test(apple.getColor(), apple.getWeight()))
result.add(apple);
}
return result;
}
public static void main(String[] args) {
List<Apple> apples = Arrays.asList(new Apple("a", 50), new Apple("b", 60));
List<Apple> a1 = filter(apples, (a) -> a.getColor().equals("a"));
System.out.println(a1);
//使用 intpredicate
List<Apple> apples1 = filter2(apples, a -> a > 50);
System.out.println(apples1);
//使用 bipredicate 两个参数
List<Apple> apples2 = colorAndWeightFilter(apples, (a, b) -> a.equals("a") && b == 50);
System.out.println(apples2);
Predicate<Apple> com = a -> a.getColor().equals("a");
com.and(a -> a.getWeight() > 10).or(a -> a.getColor().equals("b")).test(new Apple());
}
}
Consumer:
public class Consumer {
public static void simpleConsumer(List<Apple> apples, Consumer<Apple> consumer) {
for (Apple apple : apples) {
consumer.accept(apple);
}
}
public static void biSimpleConsumer(List<Apple> apples, String color, BiConsumer<Apple, String> biConsumer) {
for (Apple apple : apples) {
biConsumer.accept(apple,color);
}
}
public static void main(String[] args) {
List<Apple> apples = Arrays.asList(new Apple("a", 50), new Apple("b", 60));
//简单的consumer
simpleConsumer(apples, System.out::println);
//biconsumer
biSimpleConsumer(apples,"a",(a,b)->{
boolean f = a.getColor().equals(b);
if (f) {
System.out.println(a);
}
});
}
}
Function:
public class Function {
public static Apple bifunction(String color, Integer weight, BiFunction<String, Integer, Apple> biFunction) {
return new Apple(color, weight);
}
public static void main(String[] args) {
//简单 function
Function<String, Integer> flambda = String::length;
//简单bifunction
Apple a = bifunction("a", 61, Apple::new);
System.out.println(a);
int i = Integer.parseInt("123");
Function<String,Integer> fun = Integer::parseInt;
Integer apply = fun.apply("123");
System.out.println(apply);
}
}