高效开发:JDK1.8的Lambada表达式
Posted Java架构师(公众号:毛奇志)
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了高效开发:JDK1.8的Lambada表达式相关的知识,希望对你有一定的参考价值。
一、 lambada表达式简介
我们知道对于Java变量可以赋给其一个值,而如果想将"一块代码(一个完整的方法)"赋给一个Java变量,如下所示,怎么做呢?
你可能认为就是下面的方式来实现
很显然,这个并不是一个很简洁的写法,我们采用Java8的Lambada表达式来实现,那么如何简化呢?
整个过程:去掉修饰符(public等)、去掉函数的名字(因为已经赋给变量,变量知道此方法名–往后知道抽象方法唯一,不需要
方法名了)、去掉返回值类型(编译器可以推断)、去掉参数类型(编译器可以推断参数类型),最终的结果是下面的形式:
分析:这样的最终结果就是把"一块代码赋给一个变量"。或者说是"这个被赋给一个变量的函数"就是一个Lambada表达式,由于Lambada可以直接赋给一个"变量",我们可以把Lambda(这里表示为变量)作为参数传递给函数。
但是变量(Lambada表达式)的类型是什么呢?所有的Lambada的类型都是一个接口,而Lambada表达式本身(“那段代码”)就是一个接口的实现,这是理解Lambada的一个关键所在,理解上可以这样认为:Lambada表达式就是产生 一个实现接口中唯一的抽象方法的子实现类的对象,因此最终结果:
Lambda 与函数式接口的关系:Lambda 依赖于函数式接口,Lambda 需要函数式接口的支持。
函数式接口:接口中只有一个需要被实现的抽象函数
说明:为了避免后来的人在接口中增加新的接口函数,导致其有多个接口函数需要被实现,变成非函数式接口,引入了一个新的Annotation(注解):@FunctionalInterface。可以把他它放在一个接口前,表示这个接口是一个函数式接口,加上它的接口不会被编译,如果加上此标记就不能再添加其他的抽象方法,否则会报错。它有点像@Override,都是声明了一种使用意图,避免你把它用错。
总结:lambda表达式本质是匿名方法
二、 Lambda 表达式的结构
2.1 Lambada表达式的语法
Lambda 表达式在Java 语言中引入了一个新的语法元素和操作符。这个操作符为 “ ->”,该操作符被称为 Lambda 操作符或箭头操作符。它将 Lambda 分为两个部分:
即:(参数列表)—>{express或statements}
左侧: 指定了 Lambda 表达式需要的方法参数列表
右侧: 指定了 Lambda 体,即 Lambda 表达式要执行的功能
2.2 使用说明
(1)一个 Lambda 表达式可以有零个或多个参数,参数的类型既可以明确声明,也可以根据上下文来推断
(2)圆括号内,方法参数列表之间用逗号相隔
(3)当只有一个参数,且其类型可推导时,圆括号()可省略
(4)Lambda 表达式的主体,如果有返回值,return也可以省略,同时body中的“;”也可以省略。匿名函数(这里指lambda表达式)的返回类型与该主体表达式一致,若没有返回值则为空;
lambda表达式本质是匿名方法
(5)Lambda 表达式的主体可包含零条或多条语句。如果 Lambda 表达式的主体只有一条语句,花括号{}可省略;如果 Lambda 表达式的主体包含一条以上语句,则表达式必须包含在花括号{}中(形成代码块)。
三、简单应用
对比匿名内部类做为参数传递和Lambda表达式作为参数来传递–Runnable,Callable接口(具体看例子)
3.1 常见的函数式接口-Runnable接口-方法没有参数没有返回值(匿名内部类作为参数传递和Lambda表达式作为参数来传)
public class LamadaDemo0 {
public static void main(String[] args) {
//匿名内部类的形式开启一个线程 需要一个Runnable接口的实现类
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("匿名内部类:我爱你!");
}
}).start();
//Lambada表达式创建匿名内部类开启一个线程
new Thread(() -> System.out.println("Lambda表达式:我爱你!")).start();
}
}
输出:
匿名内部类:我爱你!
Lambda表达式:我爱你!
3.2 常见的函数式接口-Comparable接口-方法一个参数一个返回值(匿名内部类作为参数传递和Lambda表达式作为参数来传)
public class LamadaDemo0 {
public static void main(String[] args) {
// 常见的函数式接口:Runnable、 Comparable--排序
// 需要不是一个接口实现类作为实参,需要不是一个接口实现类中的方法调用,无法用匿名内部类
Comparable<Integer> comparable=new Comparable<Integer>() {
@Override
public int compareTo(Integer o) {
return 0;
}
};
int res0 = comparable.compareTo(3);
System.out.println(res0);
//Lambada表达式的方法 去掉访问修饰符、去掉返回值、去掉方法名、只要实参和方法体和返回值
// 实参为a,返回为a
Comparable<Integer> com=(a)->a;
int res2 = com.compareTo(3);
System.out.println(res2);
}
}
输出:
0
3
3.3 Comparator接口实现类
import java.util.Comparator;
import java.util.TreeSet;
public class LamadaDemo0 {
public static void main(String[] args) {
//TreeSet排序新高度---Comparator本身有泛型
// 这里是一个接口实现类作为实参,所以可以用匿名内部类
TreeSet treeSet1 = new TreeSet<>(new Comparator<Integer>() {
@Override
public int compare(Integer a, Integer b) {
return b - a;
}
});
treeSet1.add(1);
treeSet1.add(2);
System.out.println(treeSet1);
//Lambada表达式的形式 实参为a,b,返回a-b
TreeSet treeSet2 = new TreeSet<Integer>((a, b) -> a - b);
treeSet2.add(1);
treeSet2.add(2);
System.out.println(treeSet2);
}
}
输出:
[2, 1]
[1, 2]
3.4 自定义一个函数式接口(接口里面只有一个需要实现的抽象方法,接口上加上@FunctionalInterface函数式接口注解)
public class LamadaDemo0 {
public static void main(String[] args) {
//匿名内部类
new A(new MyFunctionalInterface<String>() {
@Override
public void method(String s) {
System.out.println(s);
}
});
//Lamada表达式的用法 匿名方法
new A((s) -> System.out.println(s));
MyFunctionalInterface myFunctionalInterface = new MyFunctionalInterface<String>() {
@Override
public void method(String s) {
System.out.println(s);
}
};
myFunctionalInterface.method("您好好");
MyFunctionalInterface myFunctionalInterface1 = (s) -> System.out.println(s);
myFunctionalInterface1.method("我哈哈");
}
}
@FunctionalInterface
interface MyFunctionalInterface<T> {
void method(T s);//自定义函数式接口---注意其定义
//用一个注解 @FunctionalInterface 去检测这个接口是不是一个函数式接口
}
class A {
MyFunctionalInterface myFunctionalInterface;
public A(MyFunctionalInterface myFunctionalInterface) {
this.myFunctionalInterface = myFunctionalInterface;
}
}
输出:
您好好
我哈哈
3.5 使用function包中已有的函数式接口
import java.util.function.Supplier;
public class LamadaDemo0 {
public static void main(String[] args) {
// 匿名内部类
new A(new Supplier<Double>() {
@Override
public Double get() {
return 3.1;
}
});
//Lambda表达式 匿名方法
new A(() -> 3.1);
Supplier supplier = new Supplier<Double>() {
@Override
public Double get() {
return 3.1;
}
};
System.out.println(supplier.get());
Supplier supplier1 = () -> 3.2;
System.out.println(supplier1.get());
}
}
class A { // 新建一个类,使用Supplier作为参数
Supplier supplier;
public A(Supplier supplier) {
this.supplier = supplier;
}
}
输出:
3.1
3.2
以上是关于高效开发:JDK1.8的Lambada表达式的主要内容,如果未能解决你的问题,请参考以下文章