Java8与Scala中的Lambda表达式深入讲解

前言

最近几年Lambda表达式风靡于编程界。很多现代编程语言都把它作为函数式编程的基本组成部分。基于JVM的编程语言如Scala、Groovy及Clojure把它作为关键部分集成在语言中。而如今,(最终)Java 8也加入了这个有趣的行列。

Java8 终于要支持Lambda表达式!自2009年以来Lambda表达式已经在Lambda项目中被支持。在那时候,Lambda表达式仍被称为Java闭包。在我们进入一些代码示例以前,先来解释下为什么Lambda表达式在Java程序员中广受欢迎。

1、为什么使用Lambda表达式

Lambda表达式通常使用在图形用户界面(GUI)的开发中。一般来说,GUI编程将程序行为和事件做连接。比如,当用户按下一个按钮(触发一个事件),你的程序就需要去执行某些行为,可能是将一些数据储存到一个数据存储器中。在Swing中,可以使用ActionListener来实现:

class ButtonHandler implements ActionListener {
 public void actionPerformed(ActionEvent e) {
 //do something
 }
}

class UIBuilder {
 public UIBuilder() {
 button.addActionListener(new ButtonHandler());
 }
}

这个例子表明了 ButtonHandler 类作为一个回调替换的用法。在这里 ButtonHandler 类仅包含 ActionListener 接口定义的 actionPerformed 方法。我们可以使用匿名内部类来简化代码:

class UIBuilder {
 public UIBuilder() {
 button.addActionListener(new ActionListener() {
 public void actionPerformed(ActionEvent event) {
 //do something
 }
 })
 }
}

这样代码简洁多了。更仔细的去看代码时,就会发现我们还创建一个只生成一个实例的类,而这个实例也仅仅持有一个独立的方法。这恰好是Lambda表达式所能解决的其中一类问题。

2、Lambda表达式代替函数

一个lambda表达式从字面上讲就是一个函数。它定义了一个函数的输入参数和函数体。Java 8 中的,lambda表达式语法尚未确定,不过大致应该类似这个样子的:

(type parameter) -> function_body

一个具体的例子:

(String s1, String s2) -> s1.length() - s2.length();

这个lambda表达式用来计算两个字符串的长度差。还有一些扩展的语法,比如避免参数的类型定义(我们马上见看到例子)还有使用{和}来支持多行定义。

Collections.sort() 方法是lambda表达的理想例子。它允许我们将字符串按照长度排序:

List<String> list = Array.asList("loooooong", "short", "tiny");
Collections.sort(list, (String s1, String s2) -> s1.length() - s2.length());
> "tiny", "short", "loooooong".

所以,不像现在java必须要求的向sort方法输入一个已经实现的Comparator(比较器)而是传送一个lambda表达式我们就可以得到相同的结果。

3、Lambda表达式代替闭包

lambda表达式有许多有趣的特性。其中之一是,它们是闭包。一个闭包允许函数访问直接词法作用域之外的变量。

String outer = "java 8"
(String s1) -> s1.length() - outer.length()

在例子中,lambda表达式访问了字符串 outer 这个作用域之外定义的变量。对于内联闭包来说这是很难做到的。

4、Lambda表达式也支持类型推论

类型推论是java 7 引入的但它同样适用于lambda表达式。简单来说,类型推论意味着程序员可以在任意一个编译器能够自动推断出类型的地方省略类型定义。

如果类型推论能够应用到前面的排序lambda表达式上,那么它就能写成下面的样子:

List<String> list = Arrays.asList(...);
Collections.sort(list, (s1, s2) -> s1.length()-s2.length());

就像你所见到的一样,参数s1和s2的类型被省略了。因为编译器知道list是一个字符串集合,它知道被用来作为比较器的lambda表达式必定是相同的类型。因此,这个类型不需要显式地声明,即使你有这么做的自由。

类型推论的主要优势就是减少样板代码,如果编译器可以为我们识别类型,为什么我们必须自己定义它们。

5、珍爱Lambda表达式,远离匿名内部类

我们来体会下,为何lambda表达式和类型推论有助于简化我们前面所提到的回调例子:

class UIBuilder {
 public UIBuilder() {
 button.addActionListener(e -> //process ActionEvent e)
 }
}

我们下载直接传送一个lambda表达式进入 addActionListener 方法来代替前面定义的持有回调方法的类。除了减少模板代码和提高可读性以外,它使我们直接表达我们唯一感兴趣的事情:处理事件。

在我们了解lambda表达式更多优势之前,先来看看在Scala中的lambda表达式副本。

6、Scala中的Lambda表达式

在函数式编程中,函数是基本的构造块。Scala融合了java中的面向对象编程和函数式编程。在Scala中,一个lambda表达式是种叫做“函数”或者“函数文本”。Scala中的函数属于一等公民。它们可以被分配给vals或者vars(最终变量或者非最终变量),它们可以作为其他函数的参数,也可以组合成新的函数。

在Scala中一个函数文本写成如下形式:

(argument) => //funtion body

举例来说,前面提到的java 用来计算两个字符串长度差的 lambda 表达式,在Scala中写作如下:

(s1: String, s2 :String) => s1.length - s2.length

Scala中的函数文本也是闭包。它可以访问在直接词法作用域之外定义的变量。

val outer =10
val myFuncLiteral = (y: Int) => y * outer
val result = myFuncLiteral(2)
> 20

这个例子结果是20.

正如你所见,我们将函数文本分配给了变量 myFuncLiteral。

java 8 的lambda表达式和Scala的函数文本在语法和语义上的相似性是十分明显的。从语义上讲它们是相同的,而语法上的唯一不同就是箭头符号(java8 ->, scala =>)和我们没有提到的简化符号。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对我们的支持。

(0)

相关推荐

  • 如何更快乐的使用Java 8中的Lambda特性

    前言 Java 8 的 Lambda 特性较之于先前的泛型加入更能鼓舞人心的,我对 Lambda 的理解是它得以让 Java 以函数式思维的方式来写代码.而写出的代码是否是函数式,并不单纯在包含了多少 Lambda 表达式,而在思维,要神似. 实际中看过一些代码,为了 Lambda 表达式而 Lambda(函数式),有一种少年不识愁滋味,为赋新词强说愁的味道.从而致使原本一个简单的方调用硬生生的要显式的用类如 apply(), accept(obj) 等形式.不仅造成代码可读性差,且可测试性也变

  • 深入学习 Java 中的 Lambda

    前言 我花了相当多的阅读和编码时间才最终理解Java Lambdas如何在概念上正常工作的.我阅读的大多数教程和介绍都遵循自顶向下的方法,从用例开始,最后以概念性问题结束.在这篇文章中,我想提供一个自下而上的解释,从其他已建立的Java概念中推导出Lambdas的概念. 首先介绍下方法的类型化,这是支持方法作为一流公民的先决条件.基于此,Lambdas的概念是被以匿名类用法的进化和特例提出的.所有这一切都通过实现和使用高阶函数映射来说明. 这篇文章的主要受众是那些已掌握函数式编程基础的人,以及那

  • java中Lambda常用场景代码实例

    本文实例为大家分享了java中Lambda常用场景的具体代码,供大家参考,具体内容如下 public class test18 { /** * lambda表达式的常用场景 */ @Test public void test() { List<String> list_one = new ArrayList<>(); list_one.add("NIKE"); list_one.add("Addidas"); /** * 用在匿名内部类里简写

  • java使用lambda表达式对List集合进行操作技巧(JDK1.8)

    具体代码如下所示: import java.util.ArrayList; import java.util.List; import java.util.function.Predicate; import java.util.stream.Collectors; public class LambdaStudy { public static void main(String[] args) { //初始化list集合 List<String> list = new ArrayList&l

  • Java8使用lambda实现Java的尾递归

    前言 本篇介绍的不是什么新知识,而是对前面讲解的一些知识的综合运用.众所周知,递归是解决复杂问题的一个很有效的方式,也是函数式语言的核心,在一些函数式语言中,是没有迭代与while这种概念的,因为此类的循环通通可以用递归来实现,这类语言的编译器都对递归的尾递归形式进行了优化,而Java的编译器并没有这样的优化,本篇就要完成这样一个对于尾递归的优化. 什么是尾递归 本篇将使用递归中最简单的阶乘计算来作为例子 递归实现 /** * 阶乘计算 -- 递归解决 * * @param number 当前阶

  • Java8简单了解Lambda表达式与函数式接口

    Java8被称作Java史上变化最大的一个版本.其中包含很多重要的新特性,最核心的就是增加了Lambda表达式和StreamAPI.这两者也可以结合在一起使用.首先来看下什么是Lambda表达式. 使用Lambda表达式不仅让代码变的简单.而且可读.最重要的是代码量也随之减少很多.然而,在某种程度上,这些功能在Scala等这些JVM语言里已经被广泛使用. 并不奇怪,Scala社区是难以置信的,因为许多Java 8里的内容看起来就像是从Scala里搬过来的.在某种程度上,Java 8的语法要比Sc

  • 详解Java中的Lambda表达式

    简介 Lambda表达式是Java SE 8中一个重要的新特性.lambda表达式允许你通过表达式来代替功能接口. lambda表达式就和方法一样,它提供了一个正常的参数列表和一个使用这些参数的主体(body,可以是一个表达式或一个代码块). Lambda表达式还增强了集合库. Java SE 8添加了2个对集合数据进行批量操作的包: java.util.function 包以及java.util.stream 包. 流(stream)就如同迭代器(iterator),但附加了许多额外的功能.

  • Java8中Lambda表达式使用和Stream API详解

    前言 Java8 的新特性:Lambda表达式.强大的 Stream API.全新时间日期 API.ConcurrentHashMap.MetaSpace.总得来说,Java8 的新特性使 Java 的运行速度更快.代码更少.便于并行.最大化减少空指针异常. 0x00. 前置数据 private List<People> peoples = null; @BeforeEach void before () { peoples = new ArrayList<>(); peoples

  • Java8与Scala中的Lambda表达式深入讲解

    前言 最近几年Lambda表达式风靡于编程界.很多现代编程语言都把它作为函数式编程的基本组成部分.基于JVM的编程语言如Scala.Groovy及Clojure把它作为关键部分集成在语言中.而如今,(最终)Java 8也加入了这个有趣的行列. Java8 终于要支持Lambda表达式!自2009年以来Lambda表达式已经在Lambda项目中被支持.在那时候,Lambda表达式仍被称为Java闭包.在我们进入一些代码示例以前,先来解释下为什么Lambda表达式在Java程序员中广受欢迎. 1.为

  • Java8中的 Lambda表达式教程

     1. 什么是λ表达式 λ表达式本质上是一个匿名方法.让我们来看下面这个例子: public int add(int x, int y) { return x + y; } 转成λ表达式后是这个样子: (int x, int y) -> x + y; 参数类型也可以省略,Java编译器会根据上下文推断出来: (x, y) -> x + y; //返回两数之和 或者 (x, y) -> { return x + y; } //显式指明返回值 可见λ表达式有三部分组成:参数列表,箭头(-&g

  • Java8中的lambda表达式入门教程

    1.基本介绍 lambda表达式,即带有参数的表达式,为了更清晰地理解lambda表达式,先上代码: 1.1 两种方式的对比 1.1.1 方式1-匿名内部类 class Student{ private String name; private Double score; public Student(String name, Double score) { this.name = name; this.score = score; } public String getName() { ret

  • 详解Java8中的Lambda表达式

    Lambda是什么 Lambda表达式,也可称为闭包,是java8的新特性,作用是取代大部分内部类,优化java代码结构,让代码变得更加简洁紧凑. Lambda的基本语法 (expression)->expression 或 (expression)->{statements;} Lambda最重要特点 用()->{}代码块替代匿名内部类 //(param)->expression;//(param)->statment;//(param)->{statments};/

  • 详解Java8中的lambda表达式、::符号和Optional类

    Java8中的lambda表达式.::符号和Optional类 0. 函数式编程 函数式编程(Functional Programming)属于编程范式(Programming Paradigm)中的用语,此外还有命令式编程(Imperative Programing)等,有兴趣的同学可以自行了解,我们这里大概解释一下函数式编程,在函数式编程中,输入一旦确定了,输出都确定了,函数调用的结果只依赖于传入的输入变量和内部逻辑,不依赖于外部,这样的写出的函数没有副作用.举个例子: public cla

  • 深入理解Java中的Lambda表达式

    Java 8 开始出现,带来一个全新特性:使用 Lambda 表达式 (JSR-335) 进行函数式编程.今天我们要讨论的是 Lambda 的其中一部分:虚拟扩展方法,也叫做公共辩护(defender)方法.该特性可以让你在接口定义中提供方法的默认实现.例如你可以为已有的接口(如 List 和 Map)声明一个方法定义,这样其他开发者就无需重新实现这些方法,有点像抽象类,但实际却是接口.当然,Java 8 理论上还是兼容已有的库. 虚拟扩展方法为 Java 带来了多重继承的特性,尽管该团队声称与

  • python中的lambda表达式用法详解

    本文实例讲述了python中的lambda表达式用法.分享给大家供大家参考,具体如下: 这里来为大家介绍一下lambda函数. lambda 函数是一种快速定义单行的最小函数,是从 Lisp 借用来的,可以用在任何需要函数的地方 .下面的例子比较了传统的函数定义def与lambda定义方式: >>> def f ( x ,y): ... return x * y ... >>> f ( 2,3 ) 6 >>> g = lambda x ,y: x *

  • Android Studio中使用lambda表达式的方法

    1.module的build.gradle里buildTypes中添加: compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } 2.module的build.gradle里defaultConfig中添加: jackOptions.enabled = true 3.注意事项:jack可能会导致中文乱码,所以需要在gradle.proper

  • C++中的Lambda表达式详解

    我是搞C++的 一直都在提醒自己,我是搞C++的:但是当C++11出来这么长时间了,我却没有跟着队伍走,发现很对不起自己的身份,也还好,发现自己也有段时间没有写C++代码了.今天看到了C++中的Lambda表达式,虽然用过C#的,但是C++的,一直没有用,也不知道怎么用,就可怜的连Lambda语法都看不懂.好了,这里就对C++中的Lambda进行一个简单的总结,就算是对自己的一个交代,我是搞C++的,我是一个C++ programmer. 一段简单的Code 我也不是文艺的人,对于Lambda的

  • C++ 中的Lambda表达式写法

    小喵的唠叨话: 寒假之后,小喵在家里无所事事,最近用C++写代码的时候,用到了std::sort这个函数,每次用这个函数,小喵似乎都得查一下lambda表达式的写法.正好最近很闲,不如总结一下. 在Bing上搜索 C++ lambda ,第一条记录就是MSDN上的C++ lambda的介绍.本文也是基于这篇文章来写的. 那么接下来,我们分几个部分来介绍. 一.什么是Lambda表达式 MSDN上对lambda表达式的解释: 在 C++ 11 中,lambda 表达式(通常称为 "lambda&q

随机推荐