浅析Java 8新特性Lambda Expression
什么是Lambda Expression
对于Lambda Expression,我的理解是,它是一个函数表达式,如下:
(int x, int y) -> x - y
符号左边定义了函数的输入,右边定义了输出。在上面的例子中,我们定义了一个关于x,y的函数,这个函数的作用是计算两者之差。那么它的类型是什么呢?比如1+1这个表达式它的(返回值)类型是int。对于函数表达式,它的类型一般是由上下文定的。
把上面的例子放到具体使用环境中,如下所示,我们可以根据上下文语义判断,该Lambda Expression的(返回值)类型是Comparator。
Arrays.sort(input[], (int x, int y) -> x - y );
为什么要引入Lambda Expression
Lambda Expression是Java 8引入的一个非常重要的新特性,它也是Java第一次尝试引入函数式编程的相关内容。
关于函数式编程,我想类比javascript,在js中函数也可以作为变量的基本类型之一,并且可以当做值一样进行传递。但是在Java中,函数是绑定在对象上的,如果需要调用一个函数foo(),需要先实例化一个对象Obj,然后再调用这个对象里的该函数Obj.foo()。如果Java中可以像js一样,直接传递函数,岂不是很酷?
为了实现这个功能,用到了:
- Functional Interface 函数式编程的概念
- Java8新增的接口 Function
- Java8新增的语法 Lambda Expression
具体怎么实现呢?本质上来说是,新创建一个对象,然后实现Function接口。这个对象即可以看成是一个函数。
除此之外,Lambda Expression还可以快速地创建匿名对象并实现接口方法。
下面,对这两种模式具体讲解。
Lambda Expression的使用 - 创建对象
在面向接口的编程中,我们会遇到许多函数式接口(Functional Interface),即只包含一个抽象方法的接口,比如java.lang.Runnable和java.util.Comparator都是典型的函数式接口。在实际使用过程中,我们需要新建一个对象,然后implements这个接口,再实现该接口的抽象方法。如下所示:
// 常规方法
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
log(e.getActionCommand());
}
});
这段代码实现的功能是给这个button加一个ActionListener,然后在这个button有操作的时候,log该操作的名称。这样写起来有点复杂,实际上我们真正关心的只是那一行log的代码而已。如果使用Lambda Expression,可以大大简化代码量,如下所示:
// Lambda Expression方法
button.addActionListener(e -> log(e.getActionCommand()));
下面,再给出一个经典的Comparator的例子参考。
// 常规方法
Arrays.sort(input[], new Comparator<Integer>() {
@Override
public int compare(int a, int b) {
return (a-b); // in ascending order
}
}); // Lambda Expression方法
Arrays.sort(input[], (int a, int b) -> a-b );
下面,再给出一个常用的Runnable的例子参考。
Thread thread = new Thread(() -> {
System.out.println("Hello " + Thread.currentThread().getName());
});
thread.start();
Lambda Expression的使用 - 传递函数
前面已经提到过了,Java不能传递函数,只能传递对象。为了实现传递函数的功能,设计上采取了一个折中的方法,创建了一个Function的接口。这样一来需要被传递的函数就可以作为一个新的对象,实现这个Function接口,来进行传递。如下示例:
在该例中,(String v) -> v.length()这个Lambda表达式就是传递的方法(函数)。
public class CollectionUtils {
// 对传入的参数input进行processor操作,依旧以list的形式返回
public static List map(List input, Function processor) {
ArrayList result = new ArrayList();
for (T obj : input) {
result.add(processor.apply(obj));
}
return result;
} public static void main(String[] args) {
List input = Arrays.asList(new String[] {"apple", "orange", "pear"});
// 统计字符串的长度
List lengths = CollectionUtils.map(input, (String v) -> v.length());
// 将字符串转换为大写
List uppercases = CollectionUtils.map(input, (String v) -> v.toUpperCase());
}
下面,再给出一个Callable的例子。例中,delayFeedback("task", 1)就是传递的方法(函数)。
Callable<String> delayFeedback(String feedback, long sleepSeconds) {
return () -> {
TimeUnit.SECONDS.sleep(sleepSeconds);
return feedback;
};
} ExecutorService executor = Executors.newWorkStealingPool(); List<Callable<String>> tasks = Arrays.asList(
delayFeedback("task1", 1),
delayFeedback("task2", 2),
delayFeedback("task3", 3)); String result = executor.invokeAny(tasks);
反思与总结
从上面的例子中,我们大概对Lambda Expression是什么,怎么使用有了一个大概的了解。
回到最初的问题,再次反思Lambda Expression到底是个什么东西。我觉得,首先,可以把它看作一个Anonymous Class。其次,这个Class一定继承了某个Function Interface。至于这Class是什么类型的,需要根据上下文判断。
那么,什么地方可以用Lambda Expression?答案是FunctionalInterface。什么是FunctionalInterface?官方的回答是:
Conceptually, a functional interface has exactly one abstract method.
举几个常见的FunctionalInterface的例子:
@FunctionalInterface
public interface Comparator<T> @FunctionalInterface
public interface Function<T,R> @FunctionalInterface
public interface Predicate<T> public Interface ActionListener
这正好对应了文中之前出现的例子。(说明:对于第1,2,3个,Java 8 API已经用Annotation标明了它是FunctionalInterface,对于第4个,虽然没有标,但是它符合FunctionalInterface的定义,所以也是。)
链接
浅析Java 8新特性Lambda Expression的更多相关文章
- Java 8 新特性 - Lambda表达式
Lambda表达式 vs 匿名类既然lambda表达式即将正式取代Java代码中的匿名内部类,那么有必要对二者做一个比较分析.一个关键的不同点就是关键字 this.匿名类的 this 关键字指向匿名类 ...
- 浅析Java 8新特性Method Reference
什么是方法引用 我们知道了什么是Lambda Expression以及如何使用,那么,Method References又是什么呢?Oracle Java Docs中这样说: They are com ...
- Java 8新特性----Lambda
Lambda 一.如何辨别Lambda表达式 Runnable noArguments = () -> System.out.println("Hello World"); ...
- Java 8新特性--Lambda表达式作为返回值
lambda表达式作为方法的返回值:
- Java 8 新特性--Lambda表达式作为方法参数
Lambda表达式的使用场景: 当方法的参数是一个函数式接口时,可以使用Lambda表达式进行简化—— 首先,前提是Runnable接口是一个函数式接口,经过查看源码得知,确实如此: 将Runnabl ...
- Java 12 新特性介绍,快来补一补
Java 12 早在 2019 年 3 月 19 日发布,它不是一个长久支持(LTS)版本.在这之前我们已经介绍过其他版本的新特性,如果需要可以点击下面的链接进行阅读. Java 11 新特性介绍 J ...
- Java 8 新特性:Lambda、Stream和日期处理
1. Lambda 简介 Lambda表达式(Lambda Expression)是匿名函数,Lambda表达式基于数学中的λ演算得名,对应于其中的Lambda抽象(Lambda Abstract ...
- Java8新特性-Lambda表达式是什么?
目录 前言 匿名内部类 函数式接口 和 Lambda表达式语法 实现函数式接口并使用Lambda表达式: 所以Lambda表达式是什么? 实战应用 总结 前言 Java8新特性-Lambda表达式,好 ...
- Java 8 新特性——检视阅读
Java 8 新特性--检视阅读 参考 Java 8 新特性--菜鸟 Oracle 公司于 2014 年 3 月 18 日发布 Java 8 ,它支持函数式编程,新的 JavaScript 引擎,新的 ...
随机推荐
- SqlSugar ORM 入门到精通【一】入门篇
背景 SqlSugar是一款国产ORM,除了拥有媲美原生的性能 另外还有满足各种需求的功能,简单好用一分钟就能够轻松上手. 2.x版本正式在自已公司内部项目使用 3.x版本得到了更多公司的喜欢不过也会 ...
- Selenium_chromedriver与chrome版本映射表(更新至v2)
chromedriver.exe下载地址:http://chromedriver.storage.googleapis.com/index.html chromedriver版本 支持的Chrome版 ...
- Hadoop源码分类概要整理
最近突然觉得, 很多掌握的都还是很浅的原理,需要更深入细粒度去了解整个分布式系统的运转机制.于是..开始作死而又作死而又作死的源码之旅. Hadoop包的功能总共有下列几类: tool:提供一些命令行 ...
- 项目中引入composer
众所周知,composer可以自定义加载插件库和依赖,它也是用PHP写的,怎样在自己的项目中引入并使用composer呢?. 1.新建一个项目,在项目的根目录创建composer.json文件,用过一 ...
- git使用基本故障
warning: LF will be replaced by CRLF in README.md. The file will have its original line endings in y ...
- 中小研发团队架构实践之应用监控Metrics
一.Metrics简介 应用监控系统Metrics由Metrics.NET+InfluxDB+Grafana组合而成,通过客户端Metrics.NET在业务代码中埋点,Metrics.N ...
- 写好Java代码的30条经验总结(转)
成为一个优秀的Java程序员,有着良好的代码编写习惯是必不可少的.下面就让我们来看看代码编写的30条建议吧. (1) 类名首字母应该大写.字段.方法以及对象(句柄)的首字母应小写.对于所有标识符,其中 ...
- web端表格测试用例
表格测试: 表格内容列表排序功能是否正常每一栏的宽度是否足够宽,表格里的文字是否都有折行?是否有因为某一格的内容太多,而将整行的内容拉长?表格是否能左(右)添加(删除)列,表格是否能上(下)添加(删除 ...
- Netbeans简要配置许可证信息
<#if licenseFirst??>${licenseFirst}</#if>${licensePrefix}Copyright (C) <2017> < ...
- yii2自带的backend,frontend不够用,添加一个后台模块怎么做?
在复杂项目里,高级模板中的fontend.backend application明显不够,可以再添加另外的application. 例如添加一个seller application .步骤如下: 1, ...