概述
Lambda表达式是jdk8中的一个语法糖,他可以对某些匿名内部类的写法进行简化,它是函数式编程思想的一个重要体现,让我们不用关注是什么对象,而是更关注我们对数据进行了什么操作
基本格式
只关注参数和方法体,不关注方法名
(参数列表)->{代码}
例子
创建线程并启动时,可以使用匿名内部类的写法:
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("新线程run方法被执行了");
}
}).start();
可以使用Lambda的格式对其进行修改。
匿名内部类,类型是一个接口,且只有一个方法的。直接去掉方法名,使用Lambda表达式方法,不关注方法名,关注方法的参数。
new Thread(()->{
System.out.println("Lambda新线程run方法被执行了");
}).start();
如果一个匿名内部类的写法,要简化成lambda表达式,光标移动到匿名内部类上,ALT+Enter,然后就可以自动改写Lambda表达式了
Lambda省略规则
- 参数类型可以省略,编译器可以自己推导,只有一个方法的情况下,还推不出是什么类型的参数吗
- 方法体只有一句代码时,方法体的大括号,return,方法体代码的分号都可以省略
-
参考C#的Lambda
C#的Lambda和Java的有些写法上的区别,但是思想没区别
Lambda方法引用
我们在使用lambda时,如果方法体中只有一个方法的调用的话(包括构造方法),我们可以用方法引用进一步简化代码。
快捷用法
写完lambda表达式后,发现方法体只有一行代码,还是调用的方法,这时候就
Alt+Enter
,快捷键显示看能不能使用方法引用,能用就用,用不了就拉倒语法
引用类的静态方法
语法
使用前提
方法体只有一行代码
- 并且这行代码是调用了某个类的静态方法
并且我们把要重写的抽象方法中所有的参数都按照顺序传入了这个静态方法中
例子
authorStream.map(author -> author.getAge())
//方法体只有一行代码,还是调用的类的静态方法,还把方法的参数按顺序传入了这个调用的静态方法里面
.map(age->String.valueOf(age));
authorStream.map(author -> author.getAge())
//重写后的
.map(String::valueOf);
注意:如果我们所重写的方法是没有参数的,调用的方法也是没有参数的也相当于符合以上规则
引用对象的实例方法
语法
使用前提
方法体只有一行代码
- 并且这行代码是调用了某个对象的成员方法
并且我们把要重写的抽象方法中所有的参数都按照顺序传入了这个成员方法中
例子
StringBuilder sb = new StringBuilder();
authorStream.map(author -> author.getName())
//方法体只有一行代码,且调用的对象的成员方法,且把方法的参数按顺序传入了这个成员方法里面
.forEach(name->sb.append(name));
StringBuilder sb = new StringBuilder();
authorStream.map(author -> author.getName())
.forEach(sb::append);
引用类的实例方法
语法
使用前提
方法体只有一行代码
- 并且这行代码是调用了第一个参数的成员方法
并且我们把要重写的抽象方法中剩余的所有的参数都按照顺序传入了这个成员方法中
例子
interface UseString{
String use(String str,int start,int length);
}
public static String subAuthorName(String str, UseString useString){
int start = 0;
int length = 1;
return useString.use(str,start,length);
}
public static void main(String[] args) {
subAuthorName("张三", new UseString() {
@Override
public String use(String str, int start, int length) {
return str.substring(start,length);
}
});
}
public static void main(String[] args) {
subAuthorName("三更草堂", String::substring);
}
构造器引用
语法
使用前提
方法体只有一行代码
- 并且这行代码是调用了某个类的构造方法
- 并且我们把要重写的抽象方法中的所有的参数都按照顺序传入了这个构造方法中
例子
authors.stream()
//方法体只有一行,还是构造方法,并且把方法的参数传入了构造方法中
.map(name->new StringBuilder(name))
authors.stream()
.map(StringBuilder::new)