Read this article takes about 4 minutes.
What is Lambda?
We know, for a Java variable, we can assign it to a "value."
If you want to "block of code" assigned to a Java variable, how to do it?
Of course, this is not a very concise wording. Therefore, in order to make this assignment more elegant, we can remove some useless statement.
In this way, we will succeed in the very elegant "block of code" assigned to a variable. The "piece of code," or "this function is assigned to a variable" is a Lambda Expression.
In Java 8 inside, all types of Lambda is an interface, Lambda expressions itself, which is "part of the code," the need to achieve this interface. I think this is a key to understanding Lambda, can be summarized, Lambda expression itself is to implement an interface. Direct say may still be a little annoying, we continue to look at an example. We give the above plus a aBlockOfCode type:
This interface is only one type of interface functions to be implemented, we call it "function interface." In order to avoid subsequent increase in human interface functions in this interface led to its multiple interface functions need to be implemented into a "non-function interface", we can add a statement @FunctionalInterface, so that others will not be able to add on the inside in the above the new interface function of:
In this way, we get a complete statement of Lambda expressions:
The most intuitive effect is to make the code becomes incredibly easy.
We can compare Lambda expressions and traditional Java implementation of the same interface:
这两种写法本质上是等价的。但是显然,Java 8中的写法更加优雅简洁。并且,由于Lambda可以直接赋值给一个变量,我们就可以直接把Lambda作为参数传给函数, 而传统的Java必须有明确的接口实现的定义,初始化才行:
有些情况下,这个接口实现只需要用到一次。传统的Java 7必须要求你定义一个“污染环境”的接口实现MyInterfaceImpl,而相较之下Java 8的Lambda, 就显得干净很多。
直接上例子。
假设Person的定义和List<Person>的值都给定。
现在需要你打印出guiltyPersons List里面所有LastName以"Z"开头的人的FirstName。
当然可以。在Java 8中有一个函数式接口的包,里面定义了大量可能用到的函数式接口(java.util.function (Java Platform SE 8 ))。
所以,我们在这里压根都不需要定义NameChecker和Executor这两个函数式接口,直接用Java 8函数式接口包里的Predicate<T>和Consumer<T>就可以了——因为他们这一对的接口定义和NameChecker/Executor其实是一样的。
第一步简化 - 利用函数式接口包:
静态函数里面的for each循环其实是非常碍眼的。这里可以利用Iterable自带的forEach()来替代。forEach()本身可以接受一个Consumer<T> 参数。
第二步简化 - 用Iterable.forEach()取代foreach loop:
第三步简化 - 利用stream()替代静态函数:
对比最开始的Lambda写法,这里已经非常非常简洁了。但是如果,我们要求变一下,变成print这个人的全部信息,及p -> System.out.println(p); 那么还可以利用Method reference来继续简化。所谓Method reference, 就是用已经写好的别的Object/Class的method来代替Lambda expression。格式如下:
第四步简化 - 如果是println(p),则可以利用Method reference代替forEach中的Lambda表达式:
这基本上就是能写的最简洁的版本了。
这里假设我们有一个person object,以及一个person object的Optional wrapper:
我们现在就来对比一下下面四种常见的null处理中,Java 8的Lambda+Optional<T>和传统Java两者之间对于null的处理差异。
情况一 - 存在则开干
由上述四种情况可以清楚地看到,Optional<T>+Lambda可以让我们少写很多ifElse块。尤其是对于情况四那种夺命连环null检查,传统java的写法显得冗长难懂,而新的Optional<T>+Lambda则清新脱俗,清楚简洁。
总之,我只是一如既往地介绍个大概,让你大概知道,哦!原来是这样子就OK了。网上关于Lambda有很多相关的教程,多看多练。假以时日,必定有所精益。
·END·
程序员的成长之路
路虽远,行则必至
本文原发于 同名微信公众号「程序员的成长之路」,回复「1024」你懂得,给个赞呗。
回复 [ 520 ] 领取程序员最佳学习方式
回复 [ 256 ] 查看 Java 程序员成长规划