相关概念

函数式编程

函数式编程(Functional Programming)思想以函数为基本运算单元,函数可以允许函数作为参数,也可以返回函数。Lambda表达式是一种函数式编程风格。

函数接口

如果一个接口只定义一个抽象方法,那么这种接口成为函数接口(Functional Interface),在Java中可以用注解@FunctionalInterface标记,这是可选的,当使用此标记时,编译器会自动检查是否符合函数接口规范。Lambda表达式主要用于函数接口的实现,略微抽象,但比匿名内部类实现方式更加简洁。

类型推断机制

Java编译器通过查看每个方法调用和相应声明来确定适于调用的参数类型,这种能力称作类型推断。Lambda表达式之所以可以大大简化表达,依赖的主要机制之一是Java编译器的类型推断能力。

Lambda 表达式语法

Lambda表达式是Java 8 发布的重要新特性。它依赖函数式编程风格类型推断机制,通过省略接口名、省略方法名、以及可选的省略某些表达格式,简化函数匿名内部类写法,更加简洁实现函数接口。

语法格式如下:

  • 一般形式(参数1,参数2)-> {语句1;语句2;}
  • 最简形式参数 ->语句

4部分可以省略:

  • 参数类型声明和返回值类型:可不写,编译器通过类型推断机制识别
  • **参数圆括号() **:当参数只有一个时,可以不写圆括号;但无参数或多个参数时,需写圆括号
  • **方法体括号{} **:当方法体只包含一行表达式,可不写方法体括号;当有多条语句时,需写方法体括号
  • 返回关键字:如果方法体只包含一行,可以不加返回关键词return,编译器自动返回值;若有多行表达式,则需要返回关键字。

Lambda表达式实例

  • 无参函数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//例子:通过实现Runnable接口,新建一个线程

//匿名内部类方法实现
new Thread(new Runnable(){
@Override
public void run(){
System.out.println("线程运行");
}
}).start();

//Lambda表达式
new thread(
()-> System.out.println("线程运行");
).start();

//省略接口名Runnable、方法名run;因为无参数,所以必须有圆括号();因为只有一行表达式,所以可选的省略方法体括号{}、返回关键字
  • 有参函数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
//例子:实现Comparator接口,通过自定义比较器给多个字符串排序

//匿名内部类方法实现
List<String> list = Arrays.asList("aa", "bb", "cc", "dd");
Collections.sort(list, new Comparator<String>(){
@Override
public int compare(String s1, String s2){
if(s1 == null)
return -1;
if(s2 == null)
return 1;
return s1.length()-s2.length();
}
});

//Lambda表达式
List<String> list = Arrays.asList("aa", "bb", "cc", "dd");
Collections.sort(list,(s1,s2)->{
if(s1 == null)
return -1;
if(s2 == null)
return 1;
return s1.length()-s2.length();
});
//省略接口名Comparator、方法名compare;可选的省略了参数类型声明String。由编译器自动推断

总结

Lambda表达式略微抽象,但是可以简化函数接口的匿名内部类实现表达。这里一定强调是函数接口才能使用Lambda表达式,因为Lambda表达式会省略接口名和方法名,所以对于拥有多个抽象方法的接口并不适用。

参考文章