躲不掉的 lambda 表达式
lambda 表达式是 Java8 的新特性,虽说都发布很久了,但是不到万不得已是肯定不会研究这个的,现在就是那不得不学习的时候了。
本文主要说一下什么 lambda 表达式、Java 中为什么要有 lambda 表达式以及 lambda 表达式的应用。
在 Java 面向对象的思想中,我们知道函数是不能单独存在的,函数一般会作为某个对象的功能封装在对象之中,我们传递参数也不能传递一个函数。曾经 Java 也为此挣扎过,我们看下面这段代码,创建一个线程,输出一句话。
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("Hello World !");
}
}).start();
有点基础应该都知道这是匿名内部类,但是你知道的,真正有效的代码就一行输出语句。其余代码基本没用,我们可以反过来想一下,我们创建线程是为了执行某一个任务,也就是某一个方法,那我们为何不直接传入一个方法呢?
按照这个思路,我们可以这样写伪代码。
new Thread((某某任务)).start();
好了,现在问题就出现了,如何去形容这个任务,或者说在 Java 中如何表示呢?lambda 表达式应运而生。
一个函数,可能会有入参,函数要有函数体,于是就这样定义了 lambda 表达式 “(参数1,参数2)-> { 函数体 } ” 。
但是吧,实际使用过程中,因为参数和函数体的不同,又有一些变种的写法,一个 lambda 表达式可以有零个或多个参数,参数之间用逗号相隔。空括号代表参数为空。
lambda 表达式的主体可包含零条或多条语句,如果 lambda 表达式的主体只有一条语句,花括号 { } 可省略,否则必须包含在花括号 { } 中。
OK,到这里我们就可以重写上面的线程了。
new Thread(
() -> System.out.println("Hello World ")
).start();
说到这简单回忆一下什么是 lambda 表达式,曾经 Java 中不能直接把函数做参数,为了能行,创造了 lambda 表达式,可以把 lambda 表达式理解为一个功能块,只不过匿名罢了。
其实 lambda 的出现是为了和函数式编程相呼应,函数式编程,就是用函数为主体来编程,把函数当成是代码的基本组成部分,就像变量一样。官方说法叫第一等公民。
举个例子说明一下函数式编程的特点。
计算如下表达式:
(1 + 2) * 3 - 4 传统的过程式编程,可能这样写(比较傻,为了演示效果):
int a = 1 + 2;
int b = a * 3;
int c = b - 4; 函数式编程要求使用函数,我们可以把运算过程定义为不同的函数,然后写成下面这样:
int result = subtract(multiply(add(1,2), 3), 4);
有点蒙,没关系,先理解 lambda 表达式的使用再说,lambda 表达式最常用的莫过于替换 Runnable 接口实现线程任务,还有什么用处呢?
太难的不介绍,说一个比较简单的,用于列表的迭代。
对一个列表的每一个元素进行操作,不使用 Lambda 表达式时如下:
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
for (int element : numbers) {
System.out.prinln(element);
}
使用 Lambda 表达式:
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
numbers.forEach(x -> System.out.println(x));
重点在操作上,输入是 x ,然后对 x 进行输出操作。就线程和列表迭代来说,为什么他们能接收 lambda 表达式作为参数呢?我们看看 forEach 方法的参数内部是什么。
* @since 1.8
*/
@FunctionalInterface
public interface Consumer<T> { /**
* Performs this operation on the given argument.
*
* @param t the input argument
*/
void accept(T t);
是一个接口,而这个接口被定义为函数式接口,lambda 表达式可以替换功能接口,我们就来自定义一个函数式接口来演示一下。
定义一个函数式接口:
// 定义一个功能接口或叫函数式接口
@FunctionalInterface
public interface WorkerInterface {
// 该接口中只能有一个抽象方法
public void doSomeWork();
} public class WorkerInterfaceTest { public static void execute(WorkerInterface worker) {
worker.doSomeWork();
} public static void main(String[] args) { // invoke doSomeWork using Annonymous class
execute(new WorkerInterface() {
@Override
public void doSomeWork() {
System.out.println("Worker invoked using Anonymous class");
}
});
// invoke doSomeWork using Lambda expression
execute(()->{System.out.println("Worker invoked using Lambda expression");});
}
}
总结一下最开始提出的几个问题,lambda 表达式可以理解为是一个匿名的函数,我们可以通过 lambda 表达式来代替功能接口(比方说 Runnable 接口)。函数式编程是一种编程模式,Java 为了支持它而定义了 lambda 。lambda 的应用主要在替代功能接口,列表迭代,还有一些对集合的操作上。
最后,能告诉我你现在使用 Lambda 表达式了吗,都是用在什么地方呢 ?
躲不掉的 lambda 表达式的更多相关文章
- Java 8特性探究(1):通往lambda之路与 lambda表达式10个示例
本文由 ImportNew 函数式接口 函数式接口(functional interface 也叫功能性接口,其实是同一个东西).简单来说,函数式接口是只包含一个方法的接口.比如Java标准库中的ja ...
- java lambda表达式学习笔记
lambda是函数式编程(FP,functional program),在java8中引入,而C#很早之前就有了.在java中lambda表达式是'->',在C#中是‘=>’. 杜甫说:射 ...
- C#中的委托,匿名方法和Lambda表达式
简介 在.NET中,委托,匿名方法和Lambda表达式很容易发生混淆.我想下面的代码能证实这点.下面哪一个First会被编译?哪一个会返回我们需要的结果?即Customer.ID=.答案是6个Firs ...
- 写的非常好的文章 C#中的委托,匿名方法和Lambda表达式
简介 在.NET中,委托,匿名方法和Lambda表达式很容易发生混淆.我想下面的代码能证实这点.下面哪一个First会被编译?哪一个会返回我们需要的结果?即Customer.ID=5.答案是6个Fir ...
- Python学习_列表推导和Lambda表达式
列表推导目的是减少将一个列表转换为另一个列表时所需编写的代码量,其功能也能用列表迭代完成 1.根据要求创建列表threes_and_fives(列表值包括1到15中能够被3或者5正常的数) three ...
- Lambda表达式与匿名方法
在C#2中,由于有了方法组,匿名方法,类型的协变和抗变,使得运用delegate变得很容易,在注册事件时代码变得简单易读,但是在C# 2中,代码仍然有点臃肿,大块的匿名方法会降低代码的可读性,一般我们 ...
- Java8特性详解 lambda表达式 Stream
1.lambda表达式 Java8最值得学习的特性就是Lambda表达式和Stream API,如果有python或者javascript的语言基础,对理解Lambda表达式有很大帮助,因为Java正 ...
- Java 8 Lambda表达式10个示例【存】
PS:不能完全参考文章的代码,请参考这个文件http://files.cnblogs.com/files/AIThink/Test01.zip 在Java 8之前,如果想将行为传入函数,仅有的选择就是 ...
- (转)C#中的委托,匿名方法和Lambda表达式
简介 在.NET中,委托,匿名方法和Lambda表达式很容易发生混淆.我想下面的代码能证实这点.下面哪一个First会被编译?哪一个会返回我们需要的结果?即Customer.ID=5.答案是6个Fir ...
随机推荐
- SpringData分页功能
在SpringData中实现分页功能我们需要将接口实现PagingAndSortingRepository这个接口提供了分页查询的方法 Page<T> findAll(Pageable p ...
- 第十四单元 Linux网络原理及基础设置
·ifconfig命令来维护网络(详见linux系统管理P422) 1) 掌握ifconfig命令的功能:显示所有正在启动的网卡的详细信息或设定系统中网卡的IP地址.2) 灵活应用ifconfig命令 ...
- LeetCode(102):二叉树的层次遍历
Medium! 题目描述: 给定一个二叉树,返回其按层次遍历的节点值. (即逐层地,从左到右访问所有节点). 例如:给定二叉树: [3,9,20,null,null,15,7], 3 / \ 9 20 ...
- XSS-HTML&javaSkcript&CSS&jQuery&ajax-CSS
CSS 1.表单的处理 <style> table, td, th{ border:1px; solid green;} th{ background-color:green; color ...
- poj3254 炮兵阵地弱化版,记数类dp
/* dp[i][j]表示到第i行的状态j有多少放置方式 */ #include<iostream> #include<cstring> #include<cstdio& ...
- C++ friend友元函数和友元类(转)
一个类中可以有 public.protected.private 三种属性的成员,通过对象可以访问 public 成员,只有本类中的函数可以访问本类的 private 成员.现在,我们来介绍一种例外情 ...
- 字定义JSON序列化支持datetime格式序列化
字定义JSON序列化支持datetime格式序列化 由于json.dumps无法处理datetime日期,所以可以通过自定义处理器来做扩展,如: import json from datetime i ...
- MyBatis - 6.Spring整合MyBatis
1.查看不同MyBatis版本整合Spring时使用的适配包: http://www.mybatis.org/spring/ 2.下载整合适配包 https://github.com/mybatis/ ...
- C# 操作windows服务[启动、停止、卸载、安装]
主要宗旨:不已命令形式操作windows服务 static void Main(string[] args) { var path = @"E:\开发辅助项目\WCF\WCF.Test\WC ...
- ASP.NET Web Api 2 接口API文档美化之Swagger
使用第三方提供的swgger ui 可有效提高 web api 接口列表的阅读性,并且可以在页面中测试服务接口. 但本人在查阅大量资料并进行编码测试后,发现大部分的swagger实例并不能有效运行.例 ...