Java 8 Lambda 表达式
一种匿名函数,简单地说,它是没有声明的方法,也即没有访问修饰符、返回值声明和名字。
函数式编程思想
函数式思想则尽量忽略面向对象的复杂语法——强调做什么,而不是以什么形式做。 只要能获取到结果,谁去做的,怎么做的都不重要,重视的是结果,不重视过程
Lambda 表达式与匿名类的区别
大区别在于关键词的使用。对于匿名类,关键词 this解读为匿名类,而对于 Lambda 表达式,关键词 this 解读为写就 Lambda 的外部类。
Lambda 表达式与匿名类的另一不同在于两者的编译方法。Java 编译器编译 Lambda 表达式并将他们转化为类里面的私有函数
匿名内部类
例子:
这个
RunnableImpl
类只是为了实现Runnable
接口而存在的,而且仅被使用了唯一一次,所以使用匿名内部类的语法即可省去该类的单独定义,即匿名内部类
public class ThreadNameless {
public static void main(String[] args) {
//使用匿名内部类
new Thread(new Runnable() {
@Override public void run() {
System.out.println("多线程任务执行!");
}
}).start();
//使用lambda
//新方法:
new Thread(
() -> System.out.println("Hello from thread")).start();
}
}
匿名内部类不用去实现类的定义,但是语法复杂
语义结构分析
public abstract void run();
- 无参数:不需要任何条件即可执行该方案。
- 无返回值:该方案不产生任何结果。
- 代码块(方法体):该方案的具体执行步骤。
Lamdba语法:
() -> System.out.println("多线程任务执行!")
- 前面的一对小括号即
run
方法的参数(无),代表不需要任何条件; - 中间的一个箭头代表将前面的参数传递给后面的代码;
- 后面的输出语句即业务逻辑代码。
通用表达式:
Lambda 表达式通常使用 (argument) -> (body) 语法书写,例如:
(arg1,arg2...)->{body}
(type1 arg1,type2 arg2...) -> { body }
() -> System.out.println("Hello World");
(String s) -> { System.out.println(s); }
() -> 42
() -> { return 3.1415 };
格式
由此我们可以推断出由3部分组成
- 参数
- 一个箭头
- 代码段
Lambda表达式的标准格式为:
(参数类型 参数名)->{ 代码段}
格式说明:
小括号内的语法与传统方法参数列表一致:无参数则留空;多个参数则用逗号分隔
->
是新引入的语法格式,代表指向动作大括号内的语法与传统方法体要求基本一致。
省略格式
可推导就可省略:Lambda强调的是“做什么”而不是“怎么做”,所以凡是可以根据上下文推导得知的信息,都可以省略
- 小括号内参数的类型可以省略;
- 如果小括号内有且仅有一个参,则小括号可以省略;
- 如果大括号内有且仅有一个语句,则无论是否有返回值,都可以省略大括号、return关键字及语句分号。
例子练习
打印出给定数组中的所有元素。方法不止一种。在下面的例子中,我们先是用常用的箭头语法创建 Lambda 表达式,之后,使用 Java 8全新的双冒号(::)操作符将一个常规方法转化为 Lambda 表达式:
//Old way:
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7);
for(Integer n: list) {
System.out.println(n);
}
//New way:
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7);
list.forEach(n -> System.out.println(n));
//or we can use :: double colon operator in Java 8
list.forEach(System.out::println);