Lambda表达式
Java 8的一个大亮点是引入Lambda表达式(匿名函数),使用它设计的代码会更加简洁。当开发者在编写Lambda表达式时,也会随之被编译成一个函数式接口。可以使用Lambda语法来代替匿名的内部类,代码不仅简洁,而且还可读。
函数式接口
Java8的新引入,包含函数式的设计,接口都有**@FunctionalInterface的注解**。就像这个注解的注释说明一样,它注解在接口层面,且注解的接口要有且仅有一个抽象方法
Lambda表达式学习
直接看代码,我就用多线程的代码举栗子一步一步看Lambda表达式的推导:
看代码:
不使用Lambda表达式:
public class TestLambda {
public static void main(String[] args) {
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("断剑重铸之日,骑士归来之时");
}
}).start();
}
}
运行结果:
这个代码相信小伙伴们很容易看懂。
接下来是使用Lambda表达式了,首先我们看下Lambda表达式的格式:
- ()->
- ->:被称为Lambda操作符。
- 左边:Lambda形参列表(接口中的抽象方法的形参列表)
- 右边:Lambda体(重写接口的抽象方法的方法体)
Lambda表达式的本质就是:作为接口的实例
使用Lambda表达式
public class TestLambda {
public static void main(String[] args) {
new Thread(() -> {
System.out.println("断剑重铸之日,骑士归来之时");
}).start();
}
这是Lambda表达式后的代码,基本上只保留的重写接口方法的方法体,
因为这个方法体中只有一句代码,所以可以把{}去掉。
使用Lambda表达式(最终版)
public class TestLambda {
public static void main(String[] args) {
new Thread(() -> System.out.println("断剑重铸之日,骑士归来之时")).start();
}
是不是强大到可怕?是不是简单到可怕?是不是清晰明了重点突出到可怕?这就是Lambda表达式的可怕之处,用极少的代码完成了之前一个类做的事情!能够代替实现函数式接口的匿名内部类。
关于Lambda的使用:
1、无参无返回值且只有一条执行语句:
这个就是上边那个例子
不使用Lambda表达式:
public class TestLambda {
public static void main(String[] args) {
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("断剑重铸之日,骑士归来之时");
}
}).start();
}
}
使用Lambda表达式:
public class TestLambda {
public static void main(String[] args) {
new Thread(() -> System.out.println("断剑重铸之日,骑士归来之时")).start();
}
运行结果是一样的:
2、有多条执行语句(不能省略{} ):
不使用Lambda表达式:
public class TestLambda {
public static void main(String[] args) {
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("断剑重铸之日,骑士归来之时");
System.out.println("时间不在于你拥有多少,而在于你怎样使用它");
}
}).start();
}
}
使用Lambda表达式:
public class TestLambda {
public static void main(String[] args) {
new Thread(() -> {
System.out.println("断剑重铸之日,骑士归来之时");
System.out.println("时间不在于你拥有多少,而在于你怎样使用它");
}).start();
}
}
2、只有1个参数无返回值:
不使用Lambda表达式:
public class TestLambda {
public static void main(String[] args) {
Consumer<String> con1 = new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
};
con1.accept("无形之刃,最为致命");
}
}
使用Lambda表达式:
public class TestLambda {
public static void main(String[] args) {
//数据类型可以省略,因为可以由编译器去推断
Consumer<String> con2 = (String s) -> System.out.println(s);
con2.accept("无形之刃,最为致命");
//只有一个参数()也可以省略
Consumer<String> con3 = s -> System.out.println(s);
con2.accept("无形之刃,最为致命");
}
}
3、有两个或两个以上的参数,且有返回值
使用Lambda表达式:
public class TestLambda {
public static void main(String[] args) {
new Thread(() -> {
System.out.println("断剑重铸之日,骑士归来之时");
System.out.println("时间不在于你拥有多少,而在于你怎样使用它");
}).start();
}
}
不使用Lambda表达式:
public class TestLambda {
public static void main(String[] args) {
Comparator<Integer> com1 = new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o1.compareTo(o2);
}
};
System.out.println(com1.compare(12, 21));
}
}
使用Lambda表达式:
public class TestLambda {
public static void main(String[] args) {
Comparator<Integer> com2 = (o1,o2) -> {
return o1.compareTo(o2);
};
System.out.println(com2.compare(6, 2));
//注意:return和{}要一起省略
Comparator<Integer> com3 = (o1,o2) -> o1.compareTo(o2);
System.out.println(com3.compare(6, 2));
}
}
以上就是对Lambda表达式的基本的使用。
接下来简单了解一下方法引用
方法引用
方法引用是Lambda表达式的一个简化写法。所引用的方法其实是Lambda表达式的方法体的实现,其语法结构为:
ObjectRef::methodName
左边可以是类名或者实例名,中间是方法引用符号”::”,右边是相应的方法名。
public class ReferenceTest {
public static void main(String[] args) {
Converter<String ,Integer> converter=new Converter<String, Integer>() {
@Override
public Integer convert(String from) {
return ReferenceTest.StringToInt(from);
}
};
converter.convert("120");
}
//函数式接口
@FunctionalInterface
interface Converter<F,T>{
T convert(F from);
}
public static int StringToInt(String from) {
return Integer.valueOf(from);
}
}
这时候如果用静态引用会使的代码更加简洁:
Converter<String, Integer> converter = ReferenceTest::StringToInt;
converter.convert("120");
方法引用我们可以把它看做是 仅仅调用特定方法的Lambda的一种快捷写法。
实例如下:
(Apple a) -> a.getWeight() Apple::getWeight
() -> Thread.currentThread().dumpStack() Thread.currentThread()::dumpStack
(str, i) -> str.substring(i) String::substring
(String s) -> System.out.println(s) System.out::println
方法引用可以分为三类:
指向静态方法:
(args) -> ClassName.staticMethod(args)
//可以写成
ClassName::staticMethod
指向实例对象的任意方法(arg0是ClassName类型的):
(arg0, rest) -> arg0.instanceMethod(rest)
//可以写成
ClassName::instanceMethod
指向实例对象的属性的方法引用:
(args) -> expr.instanceMethod(args)
//可以写成
expr::instanceMethod