前言
早在JAVA8出来的时候,我实际就已经了解过一点点lambda表达式和stream流,但是由于写惯了原来的那种风格,再加上当时的项目中也没有什么人使用,所以只是一扫而过,没有深入了解,也没有进行任何的练习,甚至还有那么一点抵触,觉得lambda读起来太不好懂。
但是现在过去好几年了,这份新工作的项目中也已经是大量的lambda和stream,因此是时候该好好的了解一番,以和项目组整体风格尽量一致。
示例
经过了解,lambda表达式的应用场景是,任何有函数式接口的地方。
什么是函数式接口呢,其实就是只有一个抽象方法的接口,例如常见的线程接口Runnable,只有一个run方法,还有Callable,只有一个call方法,以及常用来比较大小的Comparator,只有一个compare方法,这些都是函数式接口。
lambda表达式可以使代码更加的简洁,例如一个简单的Runnable,不用lambda会写成下边这样:
1 | Runnable run1=new Runnable() { |
改成lambda,则可以写成下边这样:
1 | Runnable run2=()->{ |
很明显,使用lambda表达式时代码简介了很多。但是实际上上边的代码还是不是最简洁的,可以进一步简写称下边这样:
1 | Runnable run3=()-> System.out.println("tuzongxun3...."); |
Runnable是没有返回值的,如果要返回值,则需要使用Callable,下边就再拿Callable做示例,不用lambda时可能会写成这样:
1 | Callable<Integer> cal1=new Callable<Integer>() { |
那么使用lambda就可以写成这样:
1 | Callable<Integer> cal2=()->{ |
同样的,上边写法也不是最简洁的,还可以进一步简化:
1 | Callable<Integer> cal3=()->1; |
上边的Runnable的run方法是没有入参也没有返回值,而Callable是没有入参有返回值,下边就再以Comparator为例,这个是既有入参,也有返回值。
这里以list倒序排序为例,假设有这样一个list:
1 | List<Integer> list=Arrays.asList(2,1,3); |
不用lambda的写法如下:
1 | list.sort(new Comparator<Integer>() { |
那么使用lambda可以写成这样:
1 | list.sort((Integer o1,Integer o2)->{return o2-o1;}); |
转化为最简洁的写法就可以是这样:
1 | list.sort((o1, o2) -> o2-o1); |
总结
那么这里就可以总结一下lambda的基本写法,即:
1 | ()->{}; |
这里的()代表方法的参数,{}代表方法体。
但是上边的写法是最标准的写法,在很多特殊情况下,都可以进一步简化。
例如在Runnable run2=()->{System.out.println("running2....");}
这个里边,因为方法体例只有一行代码,所以就可以省略外边的大括号,进而简化为下边这样:
1 | Runnable run3=()-> System.out.println("running3...."); |
再例如Callable<Integer> cal2=()->{return 1;}
中,由于方法体只是简单返回了一个结果,就可以同时去掉大括号和return关键字,进一步简化为:
1 | Callable<Integer> cal3=()->1; |
像上边list.sort((Integer o1,Integer o2)->{return o2-o1})
这一个简化为list.sort((o1, o2) -> o2-o1)
,就是去掉了方法体的大括号和return。
但是同时,这里还去掉了入参的类型Integer,原因是lambda可以自动识别参数类型。
实际上,除了上边的内容,入参的小括号也是可以省略的,但是只有当仅有一个参数的时候才能省略,没有参数或者多于一个时,都不能省略。