引言
Lambda 表达式是 Java SE 8 中一个重要的新特性。其允许你通过表达式来代替功能接口。 lambda表达式就和方法一样,它提供了一个正常的参数列表和一个使用这些参数的主体(可以是一个表达式或一个代码块)。 此外,Lambda 表达式也可以看作是一个匿名函数,基于数学中的 λ 演算得名,也称为闭包。
一、语法格式
基本语法
(parameters) -> expression; 或 (parameters) ->{ statements; };
Lambda表达式由三部分组成:
- paramaters:类似方法中的形参列表,这里的参数即为函数式接口里的参数。这里的参数类型可以明确声明,也可不声明,可由 JVM 推断。此外,当只有一个paramaters时,可以省略掉其对应圆括号。
- ->:可理解为“被用于”的意思。
- 方法体:可以是表达式也可以是代码块,是函数式接口里方法的实现。代码块可返回一个值或什么都不返回,这里的代码块等同于方法的方法体。如果是表达式,也可以返回一个值或者什么都不返回。
二、理解函数式接口
定义
如果一个接口有且仅有一个抽象方法,那么该接口称为函数式接口。
注意:如果我们在某个接口中声明了 @FunctionalInterface 注解,那么编译器就会按照函数式接口的定义来要求该接口。显然,当我们定义了两个抽象方法,程序编译就会报错。下面为函数式接口的语法
@FunctionalInterface interface NoParameterNoReturn { void test(); //注意:只能有一个抽象方法 }
三、使用 Lambda 表达式
程序清单1:
interface NoParameterNoReturn{ void test(); } public class Test1 { public static void main(String[] args) { //1. 正常实现一个接口 //一般来说,接口不能直接通过 new 来实例化对象 //但是我们可以通过 new 一个对象,相当于一个匿名内部类实现了此接口, //并重写其方法 NoParameterNoReturn noParameterNoReturn = new NoParameterNoReturn() { @Override public void test() { System.out.println("重写方法"); } }; noParameterNoReturn.test(); System.out.println("-----------------"); //2. 使用 Lambda 表达式 NoParameterNoReturn noParameterNoReturn2 = () -> System.out.println("重写方法"); noParameterNoReturn2.test(); } }
输出结果:
程序清单2:
/** * 通过使用 Lambda 表达式来测试一些接口 */ interface OneParameterNoReturn { void test(int a); } interface MoreParameterNoReturn { void test(int a,int b); } interface NoParameterReturn { int test(); } interface OneParameterReturn { int test(int a); } interface MoreParameterReturn { int test(int a,int b); } public class Test2 { public static void main(String[] args) { //1. 一个参数无返回值 //形式一 OneParameterNoReturn oneParameterNoReturn = (a)-> {System.out.println(a);}; //形式二 OneParameterNoReturn oneParameterNoReturn2 = a-> System.out.println(a); oneParameterNoReturn2.test(10); System.out.println("----------------------"); //2. 多个参数无返回值 //形式一 MoreParameterNoReturn moreParameterNoReturn = (int a, int b)->{ System.out.println(a+b); }; //形式二 MoreParameterNoReturn moreParameterNoReturn2 = (a,b)-> System.out.println(a+b); moreParameterNoReturn2.test(10,20); System.out.println("----------------------"); //3. 无参数有返回值 //形式一 NoParameterReturn noParameterReturn = ()->{return 111;}; //形式二 NoParameterReturn noParameterReturn2 = ()->111; System.out.println(noParameterReturn2.test()); System.out.println("----------------------"); //4. 一个参数有返回值 OneParameterReturn oneParameterReturn = (a)->a+5; System.out.println(oneParameterReturn.test(100)); System.out.println("----------------------"); //5. 多个参数有返回值 MoreParameterReturn moreParameterReturn = (a,b)->a*b; System.out.println(moreParameterReturn.test(5, 5)); } }
输出结果:
四、变量捕获
程序清单3:
/** * 变量捕获 */ class Out{ public void function(){ System.out.println(123); } } interface NoParameterNoReturn2 { void test(); } public class Test3 { public static void main(String[] args) { //1. 将 x 这个变量视为常量,或者这个 x 变量不能被修改 //这样一来,下面的匿名内部类才能捕获到变量 x int x = 111; //x = 999; //error new Out(){ @Override public void function() { System.out.println("捕获变量: " + x); } }.function(); //2. 同理,下面是 Lambda 的变量捕获 int a = 333; //a = 999; //error NoParameterNoReturn2 noParameterNoReturn2 = ()->{ System.out.println("捕获变量:"+ a); }; noParameterNoReturn2.test(); } }
输出结果:
五、Lambda在集合当中的使用
程序清单4:
import java.util.ArrayList; import java.util.Comparator; import java.util.function.Consumer; /** * Lambda 表达式在集合当中的使用 */ public class Test4 { public static void main(String[] args) { ArrayList<String> list = new ArrayList<>(); list.add("hello"); list.add("world"); list.add("nice"); /** * 1. 打印出来 list 中的现有元素 * 方法一: * 直接通过匿名内部类实现 Consumer 这个函数式接口 */ list.forEach(new Consumer<String>() { @Override public void accept(String str) { System.out.println(str); } }); System.out.println("---------------------"); //方法二: //Lambda 表达式的应用 list.forEach(str -> System.out.println(str)); System.out.println("---------------------"); /** * 2. 排序 list 中的现有元素 * 方法一: * 直接通过 Comparator 这个函数式接口 new 一个对象 */ list.sort(new Comparator<String>() { @Override public int compare(String o1, String o2) { return o1.compareTo(o2); } }); System.out.println(list); System.out.println("---------------------"); //方法二: //Lambda 表达式的应用 list.sort((o1, o2) -> o1.compareTo(o2)); System.out.println(list); } }
输出结果:
六、Lambda 表达式的优缺点
Lambda表达式的优点很明显,在代码层次上来说,使代码变得非常的简洁。缺点也很明显,代码不易读。
优点:
① 代码简洁,开发迅速
② 方便函数式编程
③ 非常容易进行并行计算
④ Java 引入 Lambda,改善了集合操作
缺点:
① 代码可读性变差
② 在非并行计算中,很多计算未必有传统的 for 性能要高
③ 不容易进行调试