Lambda表达式-使用说明
jdk8已经发布4年,其中有一个特性:Lambda,它是一个令开发者便捷开发的一种方式,Lambda Expression (Lambda表达式)是为了让java提供一种面向函数编程,原本在jdk8之前只支持面向对象编程,
而函数式编程则是对行为的抽象(将行为作为一个参数进行传递),接下来通过例子来说明:
这是一个线程对象,传入匿名内部类的例子:
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("Hello World!");
}
});
IDEA会给出提示可以使用Lambda表达式替换。

通过使用Lambda表达式则只需要使用一句话就可代替上面使用匿名类的方式。
new Thread(() -> System.out.println("Hello World!"));
在这个例子中,传统的语法规则,我们是将一个匿名内部类作为参数进行传递,我们实现了Runnable接口,并将其作为参数传递给Thread类,这实际上我们传递的是一段代码,也即我们将代码作为了数据进行传递,这就带来许多不必要的“样板代码”。
Lambda表达式一共有三部分组成:

后面的示例中我们会详解这个结构,包括有无参数,有无返回值的问题。 那么这个看起来奇奇怪怪的不太像Java的语法规则,其本身含义到底什么呢?这也是开始困扰我的问题,什么时候在什么场景下可以使用Lambda表达式。
能够接收Lambda表达式的参数类型,是一个只包含一个方法的接口。只包含一个方法的接口称之为“函数接口”。
例如上面创建一个线程的示例,Runnable接口只包含一个方法,所以它被称为“函数接口”,所以它可以使用Lambad表达式来代替匿名内部类。根据这个规则,我们试着来写一个函数接口,并使用Lambda表达式作为参数传递。
1 package com.coderbuff.custom;
2
3 /**
4 * 函数接口:只有一个方法的接口。作为Lambda表达式的类型
5 * Created by Kevin on 2018/2/17.
6 */
7 public interface FunctionInterface {
8 void test();
9 }
测试:
1 package com.coderbuff.custom;
2
3 import org.junit.Test;
4
5 /**
6 * 函数接口测试
7 * Created by Kevin on 2018/2/17.
8 */
9 public class FunctionInterfaceTest {
10
11 @Test
12 public void testLambda() {
13 func(new FunctionInterface() {
14 @Override
15 public void test() {
16 System.out.println("Hello World!");
17 }
18 });
19 //使用Lambda表达式代替上面的匿名内部类
20 func(() -> System.out.println("Hello World"));
21 }
22
23 private void func(FunctionInterface functionInterface) {
24 functionInterface.test();
25 }
26 }
可以看到,只要是一个接口中只包含一个方法,则可以使用Lambda表达式,这样的接口称之为“函数接口”。
上面的函数接口比较简单不包含参数,也不包含返回值。
我们再来修改FunctionInterface函数接口逐步加大Lambda表达式的难度——包含参数,不包含返回值。
1 package com.coderbuff.custom;
2
3 /**
4 * 函数接口:只有一个方法的接口。作为Lambda表达式的类型
5 * Created by Kevin on 2018/2/17.
6 */
7 public interface FunctionInterface {
8 void test(int param);
9 }
测试:
1 package com.coderbuff.custom;
2
3 import org.junit.Test;
4
5 /**
6 * 函数接口测试
7 * Created by Kevin on 2018/2/17.
8 */
9 public class FunctionInterfaceTest {
10
11 @Test
12 public void testLambda() {
13 //使用Lambda表达式代替匿名内部类
14 func((x) -> System.out.println("Hello World" + x));
15 }
16
17 private void func(FunctionInterface functionInterface) {
18 int x = 1;
19 functionInterface.test(x);
20 }
21 }
关注Lambda表达式“(x) -> Sysout.out.println("Hello World" + x)”,左边传递的是参数,此处并没有指明参数类型,因为它可以通过上下文进行类型推导,但在有些情况下不能推导出参数类型(在编译时不能推导通常IDE会提示),此时则需要指明参数类型。我个人建议,任何情况下指明函数的参数类型。
哪种情况不能推导出参数类型呢?就是函数接口是一个泛型的时候。
1 package com.coderbuff.custom;
2
3 /**
4 * 函数接口:只有一个方法的接口。作为Lambda表达式的类型
5 * Created by Kevin on 2018/2/17.
6 */
7 public interface FunctionInterface<T> {
8 void test(T param);
9 }
测试:
1 package com.coderbuff.custom;
2
3 import org.junit.Test;
4
5 /**
6 * 函数接口测试
7 * Created by Kevin on 2018/2/17.
8 */
9 public class FunctionInterfaceTest {
10
11 @Test
12 public void testLambda() {
13 //使用Lambda表达式代替匿名内部类
14 func((Integer x) -> System.out.println("Hello World" + x));
15 }
16
17 private void func(FunctionInterface<Integer> functionInterface) {
18 int x = 1;
19 functionInterface.test(x);
20 }
21 }
上面的示例提到了Lambda表达式的两种情况:
无参数,无返回值;
有参数,无返回值。
接下来就是有参数,有返回值这种较为复杂的情况。
1 package com.coderbuff.custom;
2
3 /**
4 * 函数接口:只有一个方法的接口。作为Lambda表达式的类型
5 * Created by Kevin on 2018/2/17.
6 */
7 public interface FunctionInterface<T> {
8 boolean test(T param);
9 }
测试:
1 package com.coderbuff.custom;
2
3 import org.junit.Test;
4
5 /**
6 * 函数接口测试
7 * Created by Kevin on 2018/2/17.
8 */
9 public class FunctionInterfaceTest {
10
11 @Test
12 public void testLambda() {
13 //使用Lambda表达式代替匿名内部类
14 func((Integer x) -> true);
15 }
16
17 private void func(FunctionInterface<Integer> functionInterface) {
18 int x = 1;
19 functionInterface.test(x);
20 }
21 }
此时的Lambda表达式“(Integer x) -> true”,右边是表达式的主体,直接返回true,如果有多行代码,则可以直接使用花括号表示,例如:
func((Integer x) -> {
System.out.println("Hello World" + x);
return true;
});
Lambda表达式基本的语法规则:
无参数,无返回值;
有参数,无返回值;
有参数,有返回值。
这三种基本情况已经大致清楚了,特别是需要弄清,什么时候可以使用Lambda表达式代替匿名内部类,也就是Lambda表达式的应用场景是函数接口。Lambda表达式这一新特性在JDK8中的引入,更大的好处则是集合API的更新,新增的Stream类库,使得我们在遍历使用集合时不再像以往那样不断地使用for循环。
JDK8使用集合的正确姿势
示例:计算来自“chengdu”的学生数量有多少。
在JDK8前的代码:
for (Student student : studentList) {
if (student.getCity().equals("chengdu")) {
count++;
}
}
JDK8使用集合的正确姿势:
count = studentList.stream().filter((student -> student.getCity().equals("chengdu"))).count();
API的使用“难度”恰似提高了,实际只是不熟悉而已。传统迭代的方式需要阅读完整个循环才能明白代码逻辑,JDK8通过流的方式则可以望文生义且代码量大大减小。
其中最为重要的是——Stream流。Stream的是通过函数式编程方式实现的在集合类上进行复杂操作的工具。若要详细讲解Stream的实现方式我相信再写一篇博客也不为过,所以此处不再考查Stream的内部实现。这里是想告诉大家,如果有幸使用JDK8的开发环境进行开发,尽量学习使用新的集合操作API。
有关Lambda表达式的应用太多,并发编程、响应式编程等等。
本文引用:http://www.cnblogs.com/yulinfeng/p/8452379.html
Lambda表达式-使用说明的更多相关文章
- 你知道C#中的Lambda表达式的演化过程吗?
那得从很久很久以前说起了,记得那个时候... 懵懂的记得从前有个叫委托的东西是那么的高深难懂. 委托的使用 例一: 什么是委托? 个人理解:用来传递方法的类型.(用来传递数字的类型有int.float ...
- Linq表达式、Lambda表达式你更喜欢哪个?
什么是Linq表达式?什么是Lambda表达式? 如图: 由此可见Linq表达式和Lambda表达式并没有什么可比性. 那与Lambda表达式相关的整条语句称作什么呢?在微软并没有给出官方的命名,在& ...
- 背后的故事之 - 快乐的Lambda表达式(一)
快乐的Lambda表达式(二) 自从Lambda随.NET Framework3.5出现在.NET开发者眼前以来,它已经给我们带来了太多的欣喜.它优雅,对开发者更友好,能提高开发效率,天啊!它还有可能 ...
- Kotlin的Lambda表达式以及它们怎样简化Android开发(KAD 07)
作者:Antonio Leiva 时间:Jan 5, 2017 原文链接:https://antonioleiva.com/lambdas-kotlin/ 由于Lambda表达式允许更简单的方式建模式 ...
- java8中lambda表达式的应用,以及一些泛型相关
语法部分就不写了,我们直接抛出一个实际问题,看看java8的这些新特性究竟能给我们带来哪些便利 顺带用到一些泛型编程,一切都是为了简化代码 场景: 一个数据类,用于记录职工信息 public clas ...
- 背后的故事之 - 快乐的Lambda表达式(二)
快乐的Lambda表达式 上一篇 背后的故事之 - 快乐的Lambda表达式(一)我们由浅入深的分析了一下Lambda表达式.知道了它和委托以及普通方法的区别,并且通过测试对比他们之间的性能,然后我们 ...
- CRL快速开发框架系列教程二(基于Lambda表达式查询)
本系列目录 CRL快速开发框架系列教程一(Code First数据表不需再关心) CRL快速开发框架系列教程二(基于Lambda表达式查询) CRL快速开发框架系列教程三(更新数据) CRL快速开发框 ...
- Lambda 表达式递归用法实例
注意: 使用Lambda表达式会增加额外开销,但却有时候又蛮方便的. Windows下查找子孙窗口实例: HWND FindDescendantWindows(HWND hWndParent, LPC ...
- Spark中Lambda表达式的变量作用域
通常,我们希望能够在lambda表达式的闭合方法或类中访问其他的变量,例如: package java8test; public class T1 { public static void main( ...
随机推荐
- WinServer-IIS-压缩及缓存
静态内容压缩: 默认10s内有2个客户端一起请求服务器的话,服务器就会把相关的静态内容压缩返回 动态内容压缩: 默认IIS的程序域最高可以占用CPU90%的资源,这个可以通过命令行修改 缓存和内核缓存 ...
- 史上最全: svn与git的对照(二):svn与git的相关概念
如图1是svnserver端数据的文件夹结构 以下是gitserver端的文件夹结构 纵观svn和git服务端的文件夹结构我们非常easy发现 1.有些目录还是蛮像的.甚至是一样的比方说svn中的co ...
- HDU - 4758 Walk Through Squares (AC自己主动机+DP)
Description On the beaming day of 60th anniversary of NJUST, as a military college which was Secon ...
- 杭电1596 find the safest road
find the safest road Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Ot ...
- Button的Click事件与js函数的两种不同顺序触发方式
先运行js.或者先运行Click事件,近期就遇到了这个问题,開始弄了两个button分别运行,那才叫一个蛋疼... 1.先运行js,再运行Button的Click函数 <asp:Button I ...
- WIN7使用VisualSVN建立SVN服务器
使用SVN开发十分的方便,这样就不用每次都拷贝粘贴来备份了,网上看到一篇给自己的windows电脑安装SVN服务器的使用非常方便. 1.下载安装文件(服务器端和客户端) 服务器端采用VisualSVN ...
- Web开发中 前端路由 实现的几种方式和适用场景
http://blog.csdn.net/xllily_11/article/details/51820909
- Server Tomcat v7.0 Server at localhost failed to start.解决办法(图文详解)
问题描述 Server Tomcat v7.0 Server at localhost failed to start. 解决办法 把你工作空间文件夹下的如下路径打开: <workspace-d ...
- Hbase项目(完整版)
涉及概念梳理:命名空间 4.1.1.命名空间的结构 1) Table:表,所有的表都是命名空间的成员,即表必属于某个命名空间,如果没有指定,则在default默认的命名空间中. 2) RegionSe ...
- if switch
一.基本if结构: 1.语法:if (条件){ 代码块 } 2.执行顺序:先判断条件,条件成立则行{}内的代码,不成立则跳出if结构快既不执行{}内的代码. 3.什么情况下要用基本if选择结构:当需要 ...