什么是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(newActionListener() {public voidactionPerformed(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() {

@Overridepublic int compare(int a, intb) {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 classCollectionUtils {//对传入的参数input进行processor操作,依旧以list的形式返回

public staticList map(List input, Function processor) {

ArrayList result= newArrayList();for(T obj : input) {

result.add(processor.apply(obj));

}returnresult;

}public static voidmain(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 delayFeedback(String feedback, longsleepSeconds) {return () ->{

TimeUnit.SECONDS.sleep(sleepSeconds);returnfeedback;

};

}

ExecutorService executor=Executors.newWorkStealingPool();

List> 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的例子:

@FunctionalInterfacepublic interface Comparator@FunctionalInterfacepublic interface Function@FunctionalInterfacepublic interface Predicate

public Interface ActionListener

这正好对应了文中之前出现的例子。(说明:对于第1,2,3个,Java 8 API已经用Annotation标明了它是FunctionalInterface,对于第4个,虽然没有标,但是它符合FunctionalInterface的定义,所以也是。)

链接

java expression 用法_浅析Java 8新特性Lambda Expression相关推荐

  1. java 越来越慢_浅析Java语言慢的原因

    Java在早期(比如JDK1.2以前)是很慢的,后续版本由于有许多优化手段的加入,Java正变得越来越快,所以现在也有很多关于Java和C/C++孰快孰慢的争论.我想就我自己的理解,谈一下影响Java ...

  2. java深度克隆_浅析Java中clone()方法浅克隆与深度克隆

    现在Clone已经不是一个新鲜词语了,伴随着"多莉"的产生这个词语确实很"火"过一阵子,在Java中也有这么一个概念,它可以让我们很方便的"制造&qu ...

  3. Java的反射作用_浅析Java 反射机制的用途和缺点

    反射的用途 Uses of Reflection Reflection is commonly used by programs which require the ability to examin ...

  4. java group类_浅析Java中线程组(ThreadGroup类)

    Java中使用ThreadGroup类来代表线程组,表示一组线程的集合,可以对一批线程和线程组进行管理.可以把线程归属到某一个线程组中,线程组中可以有线程对象,也可以有线程组,组中还可以有线程,这样的 ...

  5. java 张龙_张龙 JAVA5新特性学习笔记

    1.增强的for循环,这点比较简单,就不举例了,但要注意: 增强的for循环与传统的for循环相比写起来更简洁,更容易理解,但是他也有一个缺点:他失去了数组或者集合的索引信  息,如果要对数组或集合里 ...

  6. java callable用法_在Java中使用Callable和Future

    最近,我们正在开发一个监控仪表板,我们想要ping几个第三方服务器,只是为了检查它们的可用性,或者我们想要调用健康检查. 我们正在对服务器进行一系列api调用,这些服务器的IP,用户名和密码被外部化为 ...

  7. java 线程状态_浅析Java中的线程状态

    一.线程的5种状态 众所周知,Java的线程状态有5种,分别对应上图中五种不同颜色,下面对这5种状态及状态间的转化做相应的解释: 1. 初始化状态:新建一个线程对象 2. 可运行状态:其他线程调用了该 ...

  8. java变量同名_浅析Java中局部变量与成员变量同名解决技巧

    要想区分这哥俩,首先,我们得知道它们分别是什么.先从成员变量下刀. 成员变量 我们来研究一个事物: 属性:外在特征:例如人的身高,体重 行为:能够做什么:例如人有说话,打球等行为. 而在Java语言中 ...

  9. java sortedlist 用法_为什么Java中没有SortedList?

    本文翻译自:Why is there no SortedList in Java? In Java there are the SortedSet and SortedMap interfaces. ...

最新文章

  1. 研究生:我们的任务是把导师培养成院士
  2. php中的extract函数
  3. boost::histogram::axis::circular用法的测试程序
  4. Spring Boot 2 快速教程:WebFlux 集成 Thymeleaf(五)
  5. Sublime Text自定义插入当前时间的插件
  6. IEEE VIS 2018专题
  7. 计算机考研考心理学,跨专业考研心理学研究生好考吗
  8. 谈谈OSI模型和它的数据传输
  9. vue html 原始 模板,vue初始化模板套用
  10. MATLAB编写m函数理解 y=f(g(x))*h(x)
  11. hihocoder题目选讲
  12. SCons教程(7) 文件操作
  13. 什么是线性表?线性表的特点,线性表的顺序存储和链式存储
  14. 程序员如何做到高效减脂、减肥
  15. python财经数据接口包_Tushare 财经数据接口包介绍(Python)
  16. 写一个WFP驱动,拦截网络
  17. MySQL——MySQL高可用之PXC
  18. 千万要找一个程序员谈恋爱!
  19. HTML与CSS关系
  20. 企业局域网络综合配置(华为)

热门文章

  1. 中国电信网优测试软件,退CDMA时机已成熟,网友亲身测试验证中国电信网优真实原因!...
  2. 干细胞实验室专业性设计
  3. MyBatis查询数据返回null
  4. html 代码自动分段,HTML的分段与换行代码说明
  5. 使用grep分析web攻击日志
  6. 华为重磅发布5G核心芯片天罡,全球首款5G折叠屏手机2月面世
  7. Go语言中Context使用技巧
  8. barcode4j+Apache POI,批量导出条形码图片到excel
  9. QML入门教程(10) : QML圆形延时按钮
  10. labelme标注的数据分析