一、背景
(1)、lambda表达式的定义:
lambda是JavaSE8的一个重要特性,允许用lambda表达式来代替功能接口,lambda表达式和方法一样,有参数,有参数的主体(一个表达式,用花括号括起来)。
(2)、lambda表达式的语法:
基本语法:(parameters) -> expression 或 (parameters) ->{ statements; }
1、parameters:类似方法体中的形参,这里的参数是函数式接口中方法的参数。
2、->:可以理解为被用于的意思。
3、statements:接口中方法的主体,是函数式接口里的方法实现,这里可以有返回,也可以没有。
(3)、函数式接口
定义:就是一个接口只有一个抽象方法。
注意:1、接口中只有一个抽象方法的才是函数式接口。
2、@FunctionalInterface 注解 的作用是加了后编译器会按函数式接口的定义来要求该接口,如果该接口有两个抽象方法,则会报错,也可以不加,但是写的时候也要注意,函数式接口只能一个抽象方法。
二、lambada表达式的基本使用
首先,我们先准备好几个函数式接口,代码如下:
//无返回值无参数 @FunctionalInterface interface NoParameterNoReturn { void test(); } //无返回值一个参数 @FunctionalInterface interface OneParameterNoReturn { void test(int a); } //无返回值多个参数 @FunctionalInterface interface MoreParameterNoReturn { void test(int a,int b); } //有返回值无参数 @FunctionalInterface interface NoParameterReturn { int test(); } //有返回值一个参数 @FunctionalInterface interface OneParameterReturn { int test(int a); } //有返回值多参数 @FunctionalInterface interface MoreParameterReturn { int test(int a,int b); }
(1)没有使用lambda表达式,简单调用函数式接口展示
lambda表达式也可以理解为简化的匿名内部类,实际上就是创建了一个类,实现了接口,重写了接口里面的方法。
没有使用lambda表达式,我们调用 NoParameterNoReturn函数接口的方法代码如下:
//无返回值无参数 @FunctionalInterface interface NoParameterNoReturn { void test(); } public class Test { public static void main(String[] args) { NoParameterNoReturn noParameterNoReturn = new NoParameterNoReturn() { @Override public void test() { System.out.println("重写了NoParameterNoReturn接口的方法"); } }; noParameterNoReturn.test(); } }
创建一个类,实现NoParameterNoReturn接口,重写了函数式接口的方法。
代码执行结果如下:
(2)上述接口的具体lambda表达式展示
1、无返回值无参数(NoParameterNoReturn)
代码如下:
//无返回值无参数 @FunctionalInterface interface NoParameterNoReturn { void test(); } NoParameterNoReturn noParameterNoReturn = () -> { System.out.println("重写了test方法");}; noParameterNoReturn.test();
代码执行结果如下:
2、无返回值一个参数(OneParameterNoReturn)
代码如下:
//无返回值一个参数 @FunctionalInterface interface OneParameterNoReturn { void test(int a); } public static void main(String[] args) { //不使用lambda表达式 OneParameterNoReturn oneParameterNoReturn1 = new OneParameterNoReturn() { @Override public void test(int a) { System.out.println("重写了带有一个参数的test方法,参数为:" + a); } }; oneParameterNoReturn1.test(10); System.out.println("==================="); //使用lambda表达式 OneParameterNoReturn oneParameterNoReturn2 = (int a) -> { System.out.println("重写了带有一个参数的test方法,参数为:" + a);}; oneParameterNoReturn2.test(20); }
代码执行结果如下:
3、无返回值多个参数(MoreParameterNoReturn)
代码如下:
//无返回值多个参数 @FunctionalInterface interface MoreParameterNoReturn { void test(int a,int b); } public static void main(String[] args) { //不使用lambda表达式 MoreParameterNoReturn moreParameterNoReturn1 = new MoreParameterNoReturn() { @Override public void test(int a, int b) { System.out.println("重写了带有2个参数的test方法,参数:" + a + " " + b); } }; moreParameterNoReturn1.test(10,20); //使用lambda表达式 MoreParameterNoReturn moreParameterNoReturn2 = (int a, int b) -> {System.out.println("重写了带有2个参数的test方法,参数:" + a + " " + b);}; moreParameterNoReturn2.test(30,40); }
代码执行结果如下:
4、有返回值无参数(NoParameterReturn)
代码如下:
//有返回值无参数 @FunctionalInterface interface NoParameterReturn { int test(); } public static void main(String[] args) { //不使用lambda表达式 NoParameterReturn noParameterReturn1 = new NoParameterReturn() { @Override public int test() { System.out.println("重写了不带参数的test方法,有返回值"); return 10; } }; System.out.println(noParameterReturn1.test()); System.out.println("======================"); //使用lambda表达式 NoParameterReturn noParameterReturn = () -> {System.out.println("重写了不带参数的test方法,有返回值");return 20;}; System.out.println(noParameterReturn.test()); }
代码结果如下:
5、有返回值一个参数(OneParameterReturn)
代码如下:
//有返回值一个参数 @FunctionalInterface interface OneParameterReturn { int test(int a); } public static void main(String[] args) { //不使用lambda表达式 OneParameterReturn oneParameterReturn1 = new OneParameterReturn() { @Override public int test(int a) { System.out.println("重写了带有一个参数的test方法,参数:" + a); return a; } }; System.out.println(oneParameterReturn1.test(10)); //使用lambda表达式 OneParameterReturn oneParameterReturn2 = (int a) -> {System.out.println("重写了带有一个参数的test方法,参数:" + a);return a;}; System.out.println(oneParameterReturn2.test(20)); }
代码结果如下:
6、有返回值多参数(MoreParameterReturn )
代码如下:
//有返回值多参数 @FunctionalInterface interface MoreParameterReturn { int test(int a,int b); } public static void main(String[] args) { MoreParameterReturn moreParameterReturn1 = new MoreParameterReturn() { @Override public int test(int a, int b) { System.out.println("重写了带有一个参数的test方法,参数:" + a + " " + b); return a + b; } }; System.out.println(moreParameterReturn1.test(10, 10)); MoreParameterReturn moreParameterReturn2 = (int a, int b) -> {System.out.println("重写了带有一个参数的test方法,参数:" + a + " " + b);return a + b;}; System.out.println(moreParameterReturn2.test(20, 20)); }
代码结果如下:
三、变量捕获
(1)、匿名内部类的简单使用
class TestDemo { public void func(){ System.out.println("func()"); } } public class Test2 { public static void main(String[] args) { //匿名内部类的简单使用 TestDemo testDemo = new TestDemo() { public void func() { System.out.println("我是内部类,且重写了func这个方法!"); } }; testDemo.func(); } }
代码结果如下:
(2)、匿名内部类变量的捕获
class TestDemo { public void func(){ System.out.println("func()"); } } public static void main(String[] args) { int a = 100; //匿名内部类变量的捕获 TestDemo testDemo = new TestDemo() { public void func() { //a = 99;err System.out.println("我是内部类,且重写了func这个方法!"); System.out.println("捕获了a:" + a); } }; testDemo.func(); }
代码结果如下:
(3)、Lambda变量的捕获
@FunctionalInterface interface NoParameterNoReturn1 { void test(); } public static void main(String[] args) { int a = 100; NoParameterNoReturn noParameterNoReturn = () -> { //a = 99;err System.out.println("捕获变量:"+a);}; noParameterNoReturn.test(); }
代码结果如下:
四、lambda在集合中的使用(map和set)
为了能够让Lambda和Java的集合类集更好的一起使用,集合当中,也新增了部分接口,以便与Lambda表达式对接。
(1)、Collection接口
forEach() 方法演示:
该方法在接口 Iterable 当中,原型如下:
该方法表示:对容器中的每个元素执行action指定的动作
forEach() 的使用,代码如下:
public static void main(String[] args) { //不使用lambda表达式 ArrayList<String> list1 = new ArrayList<>(); list1.add("hello"); list1.add("word"); list1.add("bit"); list1.add("lambda"); list1.forEach(new Consumer<String>() { @Override public void accept(String s) { System.out.print(s + " "); } }); System.out.println(); System.out.println("============="); //使用lambda表达式 ArrayList<String> list2 = new ArrayList<>(); list2.add("hello"); list2.add("word"); list2.add("bit"); list2.add("lambda"); list2.forEach((String x) -> {System.out.print(x + " ");}); }
代码结果如下:
(2)、List接口
sort()方法的演示:
sort方法源码:该方法根据c指定的比较规则对容器元素进行排序。
sort() 的使用:
public static void main(String[] args) { //不使用lambda表达式 ArrayList<String> list1 = new ArrayList<>(); list1.add("hello"); list1.add("word"); list1.add("bit"); list1.add("lambda"); list1.sort(new Comparator<String>() { @Override public int compare(String o1, String o2) { return o1.length() - o2.length(); } }); System.out.println(list1); System.out.println("==================="); //使用lambda表达式 ArrayList<String> list2 = new ArrayList<>(); list2.add("hello"); list2.add("word"); list2.add("bit"); list2.add("lambda"); list2.sort((String o1, String o2) -> {return o1.length() - o2.length();}); System.out.println(list2); }
代码结果如下:
(2)、map接口
HashMap 的 forEach()
该方法原型如下:
作用是对Map中的每个映射执行action指定的操作。
forEach() 方法演示:
public static void main(String[] args) { //不使用lambda表达式 HashMap<Integer, String> map1 = new HashMap<>(); map1.put(1, "hello"); map1.put(2, "word"); map1.put(3, "bit"); map1.put(4, "lambda"); map1.forEach(new BiConsumer<Integer, String>() { @Override public void accept(Integer integer, String s) { System.out.print(integer + "=" + s + " "); } }); System.out.println(); System.out.println("============="); //使用lambda表达式 HashMap<Integer, String> map2 = new HashMap<>(); map2.put(1, "hello"); map2.put(2, "word"); map2.put(3, "bit"); map2.put(4, "lambda"); map2.forEach((Integer a, String b) -> {System.out.print(a + "=" + b + " ");}); }
结果如下:
五、优缺点
优点:
1、代码简洁,开发迅速
2、方便函数式编程
3、非常容易进行并行计算
4、java引入了lambda表达式,改善了集合操作
缺点:
1、代码可读性差
2、在非并行计算中,性能未必比传统的for性能高
3、不容易进行调试