- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章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来实现
1
2
3
4
5
6
7
8
9
10
11
|
class
buttonhandler
implements
actionlistener {
public
void
actionperformed(actionevent e) {
//do something
}
}
class
uibuilder {
public
uibuilder() {
button.addactionlistener(
new
buttonhandler());
}
}
|
这个例子表明了 buttonhandler 类作为一个回调替换的用法。在这里 buttonhandler 类仅包含 actionlistener 接口定义的 actionperformed 方法。我们可以使用匿名内部类来简化代码:
1
2
3
4
5
6
7
8
9
|
class
uibuilder {
public
uibuilder() {
button.addactionlistener(
new
actionlistener() {
public
void
actionperformed(actionevent event) {
//do something
}
})
}
}
|
这样代码简洁多了。更仔细的去看代码时,就会发现我们还创建一个只生成一个实例的类,而这个实例也仅仅持有一个独立的方法。这恰好是lambda表达式所能解决的其中一类问题.
2、lambda表达式代替函数 。
一个lambda表达式从字面上讲就是一个函数。它定义了一个函数的输入参数和函数体。java 8 中的,lambda表达式语法尚未确定,不过大致应该类似这个样子的:
1
|
(type parameter) -> function_body
|
一个具体的例子:
1
|
(string s1, string s2) -> s1.length() - s2.length();
|
这个lambda表达式用来计算两个字符串的长度差。还有一些扩展的语法,比如避免参数的类型定义(我们马上见看到例子)还有使用{和}来支持多行定义.
collections.sort() 方法是lambda表达的理想例子。它允许我们将字符串按照长度排序:
1
2
3
|
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表达式有许多有趣的特性。其中之一是,它们是闭包。一个闭包允许函数访问直接词法作用域之外的变量.
1
2
|
string outer =
"java 8"
(string s1) -> s1.length() - outer.length()
|
在例子中,lambda表达式访问了字符串 outer 这个作用域之外定义的变量。对于内联闭包来说这是很难做到的.
4、lambda表达式也支持类型推论 。
类型推论是java 7 引入的但它同样适用于lambda表达式。简单来说,类型推论意味着程序员可以在任意一个编译器能够自动推断出类型的地方省略类型定义.
如果类型推论能够应用到前面的排序lambda表达式上,那么它就能写成下面的样子:
1
2
|
list<string> list = arrays.aslist(...);
collections.sort(list, (s1, s2) -> s1.length()-s2.length());
|
就像你所见到的一样,参数s1和s2的类型被省略了。因为编译器知道list是一个字符串集合,它知道被用来作为比较器的lambda表达式必定是相同的类型。因此,这个类型不需要显式地声明,即使你有这么做的自由.
类型推论的主要优势就是减少样板代码,如果编译器可以为我们识别类型,为什么我们必须自己定义它们.
5、珍爱lambda表达式,远离匿名内部类 。
我们来体会下,为何lambda表达式和类型推论有助于简化我们前面所提到的回调例子:
1
2
3
4
5
|
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中一个函数文本写成如下形式:
1
|
(argument) =>
//funtion body
|
举例来说,前面提到的java 用来计算两个字符串长度差的 lambda 表达式,在scala中写作如下:
1
|
(s1: string, s2 :string) => s1.length - s2.length
|
scala中的函数文本也是闭包。它可以访问在直接词法作用域之外定义的变量.
1
2
3
4
|
val outer =
10
val myfuncliteral = (y:
int
) => y * outer
val result = myfuncliteral(
2
)
>
20
|
这个例子结果是20. 。
正如你所见,我们将函数文本分配给了变量 myfuncliteral.
java 8 的lambda表达式和scala的函数文本在语法和语义上的相似性是十分明显的。从语义上讲它们是相同的,而语法上的唯一不同就是箭头符号(java8 ->, scala =>)和我们没有提到的简化符号.
总结 。
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对我的支持.
原文链接:https://yq.aliyun.com/articles/657841 。
最后此篇关于Java8与Scala中的Lambda表达式深入讲解的文章就讲到这里了,如果你想了解更多关于Java8与Scala中的Lambda表达式深入讲解的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我正在用 yacc/bison 编写一个简单的计算器。 表达式的语法看起来有点像这样: expr : NUM | expr '+' expr { $$ = $1 + $3; } | expr '-'
我开始学习 lambda 表达式,并在以下情况下遇到了以下语句: interface MyNumber { double getValue(); } MyNumber number; nu
这两个 Linq 查询有什么区别: var result = ResultLists().Where( c=> c.code == "abc").FirstOrDefault(); // vs. va
如果我们查看 draft C++ standard 5.1.2 Lambda 表达式 段 2 说(强调我的 future ): The evaluation of a lambda-expressio
我使用的是 Mule 4.2.2 运行时、studio 7.5.1 和 Oracle JDK 1.8.0_251。 我在 java 代码中使用 Lambda 表达式,该表达式由 java Invoke
我是 XPath 的新手。我有网页的html源 http://london.craigslist.co.uk/com/1233708939.html 现在我想从上面的页面中提取以下数据 完整日期 电子
已关闭。这个问题是 off-topic 。目前不接受答案。 想要改进这个问题吗? Update the question所以它是on-topic用于堆栈溢出。 已关闭10 年前。 Improve th
我将如何编写一个 Cron 表达式以在每天上午 8 点和下午 3:30 触发?我了解如何创建每天触发一次的表达式,而不是在多个设定时间触发。提前致谢 最佳答案 你应该只使用两行。 0 8 * * *
这个问题已经有答案了: What do 3 dots next to a parameter type mean in Java? (9 个回答) varargs and the '...' argu
我是 python 新手,在阅读 BeautifulSoup 教程时,我不明白这个表达式“[x for x in titles if x.findChildren()][:-1]”我不明白?你能解释一
(?:) 这是一个有效的 ruby 正则表达式,谁能告诉我它是什么意思? 谢谢 最佳答案 正如其他人所说,它被用作正则表达式的非捕获语法,但是,它也是正则表达式之外的有效 ruby 语法。 在
这个问题在这里已经有了答案: Why does ++[[]][+[]]+[+[]] return the string "10"? (10 个答案) 关闭 8 年前。 谁能帮我处理这个 JavaSc
这个问题在这里已经有了答案: What is the "-->" operator in C++? (29 个答案) Java: Prefix/postfix of increment/decrem
这个问题在这里已经有了答案: List comprehension vs. lambda + filter (16 个答案) 关闭 10 个月前。 我不确定我是否需要 lambda 或其他东西。但是,
C 中的 assert() 函数工作原理对我来说就像一片黑暗的森林。根据这里的答案https://stackoverflow.com/a/1571360 ,您可以使用以下构造将自定义消息输出到您的断言
在this页,John Barnes 写道: If the conditional expression is the argument of a type conversion then effec
我必须创建一个调度程序,它必须每周从第一天上午 9 点到第二天晚上 11 点 59 分运行 2 天(星期四和星期五)。为此,我需要提供一个 cron 表达式。 0-0 0-0 9-23 ? * THU
我正在尝试编写一个 Linq 表达式来检查派生类中的属性,但该列表由来自基类的成员组成。下面的示例代码。以“var list”开头的 Process 方法的第二行无法编译,但我不确定应该使用什么语法来
此 sed 表达式将输入字符串转换为两行输出字符串。两条输出行中的每一行都由输入的子串组成。第一行需要转换成大写: s:random_stuff\(choice1\|choice2\){\([^}]*
我正在使用 Quartz.Net 在我的应用程序中安排我的工作。我只是想知道是否可以为以下场景构建 CRON 表达式: Every second between 2:15AM and 5:20AM 最
我是一名优秀的程序员,十分优秀!