- 浏览: 3513973 次
- 性别:
- 来自: 大连
博客专栏
-
使用Titanium Mo...
浏览量:37478
-
Cordova 3.x入门...
浏览量:604304
-
常用Java开源Libra...
浏览量:678049
-
搭建 CentOS 6 服...
浏览量:87250
-
Spring Boot 入...
浏览量:399811
-
基于Spring Secu...
浏览量:69066
-
MQTT入门
浏览量:90468
文章分类
最新评论
-
afateg:
阿里云的图是怎么画出来的?用什么工具?
各云服务平台的架构图 -
cbn_1992:
博主,采用jdbctoken也就是数据库形式之后,反复点击获取 ...
Spring Security OAuth2 Provider 之 数据库存储 -
ipodao:
写的很是清楚了,我找到一份中文协议:https://mcxia ...
MQTT入门(6)- 主题Topics -
Cavani_cc:
还行
MQTT入门(6)- 主题Topics -
fexiong:
博主,能否提供完整源码用于学习?邮箱:2199611997@q ...
TensorFlow 之 构建人物识别系统
Java 8历时2年8个月,这次升级是继Java 5之后对Java一次脱胎换骨的变化。在Java 8的新特性中很多都是围绕Lambda表达式而提供的,Lambda表达式也将使热衷于OOP(Object-Oriented Programming)的Java程序员体会到FP(Functional Programming)的强大。Java 8的Lambda表达多少借鉴了Scala的Lambda(Scala使用「=>」Java8使用「->」),和纯正FP的Haskell还是有很大差别。
(1)历史来由
①关于Java7/Java8
Java 8的很多新特性按照预定都应该包含在Java 7中,但是由于对Project Lambda和Project Jigsaw的争论一直没有达成共识,Java 7一直无法发布。2010年9月Java平台首席架构师Mark Reinhold在他的Blog上提出2个方案:
2012年7月 Mark Reinhold再次发文称Project Jigsaw将不会包含在Java 8中而得推迟到Java 9中,由此一来Java 8的主要特性就是Project Lambda。
2012年下旬->2013年下旬->2014年3月 Java 8的发布也是不断跳票。Project Coin、Collection Literals、Swing Date Picker等也被推迟到Java 9,而把Date & Time API、Nashorn等纳入Java 8中。
2014年3月18日 Java 8带着“即使有Bug也要发布”的节奏,历时2年8个月终于发布了。JavaTM SE 8 Release Contents
②关于Project Lambda
2005年,Java 6发布前很多人提议在Java中引入闭包Closure,先是Gilad Bracha、Neal Gafter、James Gosling、Peter van der Ahé做了一个Java闭包的提案,叫BGGA(以他们名字的首字母命名)、后来改名Closures for the Java Programing Language。关于这个提案在Java社区掀起了很到争论,Neal Gafter和Joshua Bloch争论最为有名。
除BGGA外,Java闭包的实现也有很多其他的方案,比如:Joshua Bloch、Doug Lea、Bob Lee提出了CICE(Concise Instance Creation Expresions)。还有一个提案是FCM(First Class Methods)。CICE并不是要在Java中引入闭包而是对匿名类做一个简化写法的提案(现在最终的Project Lambda也是很接近CICE)。
2008年在java.net做了一个在线调查,大概2000人参与回答,大部分人投给了BGGA或者干脆不引入闭包。
2008年11月,Mark Reinhold在 Devoxx 发布Java 7中不会引入闭包,从而才终止了这场争论。但是1年后的2009年11月Mark Reinhold同样是在 Devoxx 发布Java 7中要引入简单的闭包。基于此,2009年12月作为OpenJDK的子项目Project Lambda开始启动。
为什么2008年终止在Java 7中引入闭包会在2009年再次提出?
答案是:CPU多核化的趋势。无论是PC还是SmartPhone,CPU的多核化在急速发展,所以软件的并行处理也要跟得上。
Java中虽然可以通过Thread来并行处理,但是Java 5的Concurrency Utilities的处理粒度更大,而Java 7的Fork/Join Framework并行粒度更细。Java的for循环采用外部迭代(程序员自己写代码),需要转成内部迭代(由Java类库迭代)的并行化,而很多语言都已经支持内部迭代。虽然Java可以借助匿名类来实现,但是写法很繁琐,所以需要简化匿名类的写法。
2009年Project Lambda成立后,Mark Reinhold提出了一个原案Straw-Man Proposal。在这个稻草人提议中Mark Reinhold并没有使用以前争论不休的闭包,而是采用了Lambda表达式。基于此草案不断演化才得到了现在Java8的Lambda表达式。JSR 335: Lambda Expressions for the Java™ Programming Language:
接口的变化:
开始决定使用SAM(Single Abstract Method)来作为接口,SAM指只有一个方法的抽象类或接口。但函数型的引入又激起了争论,后来只限于接口,所以很少人再说SAM,而是引入了函数式接口的概念。
写法的变化:
#(参数) { 函数体 } -> (参数) -> { 函数体 }
Collections.xxxx() -> Stream API
实现的变化
匿名类 ->Java 7 引入的 InvokeDynamic命令动态生成Class
Project Lambda是一个漫长的过程,能够最终成行已经不易,看看这些人的名字,他们都是Java界的大神,尤其Doug Lea为Java并发做出了不可磨灭的贡献。
(2)Lambda表达式
λ:希腊字母表中排序第十一位的字母,英语名称为Lambda。最早出现是用于计算的λ演算(lambda calculus),后来被函数式编程语言广泛采用。
Lambda表达式可以理解成为是一个能够作为参数传递的匿名函数Object,他没有名字,但有参数列表、有函数体、有返回类型、可以抛出异常。它的类型,叫做“目标类型(target type)”Java8中就是“函数接口(functional interface)”。
语法:
举例:
①省略类型
***不能只省略一部分类型,比如:(int x, y) -> { return x + y; }; // NG
②1个参数可以省略括号
***但是不能带类型,比如:String text -> { System.out.println(text); }; // NG
③函数体多行时需要大括号
④函数体只有一行的话可以省略大括号
***assert语句不能省略带括号,比如: s -> { assert !s.isEmpty(); };
***return语句不能省略带括号,比如:(x, y) -> return x -y; // NG
⑤只有一行代码而且有返回值的可以省略return,会返回该行代码计算结果
***return要和大括号一起省略,比如:(x, y) -> { x - y; }; // NG
⑥没有参数没有返回值的空函数
⑦Scala等使用下划线做占位符,Java8中不可以
⑧用于Lambda的变量不可变
⑨其他
(3)Lambda和匿名类区别
this:匿名类this取得是自己,Lambda取得是所在的外部类。
****但是很少需要在lambda中使用this
(4)用于何处
Lambda可以传递给任何希望是函数式接口的地方。
(5)运行机制
Java 7引入了invokedynamic指令,它是一个JVM指令,允许动态语言在run-time时动态绑定。Java 8的Lambda表达式并不是匿名类的语法糖,它不会在编译的时候生成类似于匿名类的xxx$1.class,而是在运行的时候使用invokeDynamic指令。对于一条Lambda表达式在class里边会包含一个invokedynamic命令和一个静态方法。运行时会使用LambdaMetafactory#metafactory做成一个Lambda$1的内部类再调用该函数式接口的实例。在运行时生成class,就是避免class太多影响加载速度,像Stream那样的到处是Lambda。
比如遍历List:
编译后的Class内容:
也可以接住异常堆栈信息看看Lambda是怎么执行的:
参考:
http://www.oracle.com/events/us/en/java8/index.html
http://www.lambdafaq.org/
http://cr.openjdk.java.net/~briangoetz/lambda/lambda-translation.html
http://www.oracle.com/webfolder/technetwork/tutorials/obe/java/Lambda-QuickStart/index.html
http://www.dreamsyssoft.com/java-8-lambda-tutorial/index.php
http://www.slideshare.net/bitter_fox/java8-launch
http://www.slideshare.net/miyakawataku/lambda-meets-invokedynamic
http://cr.openjdk.java.net/~briangoetz/lambda/lambda-state-final.html
http://www.slideshare.net/mariofusco/fp-in-java-project-lambda-and-beyond
http://www.journaldev.com/2389/java-8-features-for-developers-lambdas-functional-interface-stream-and-time-api
这一句应该是有问题的
一个是参数,一个是返回值
(1)历史来由
①关于Java7/Java8
Java 8的很多新特性按照预定都应该包含在Java 7中,但是由于对Project Lambda和Project Jigsaw的争论一直没有达成共识,Java 7一直无法发布。2010年9月Java平台首席架构师Mark Reinhold在他的Blog上提出2个方案:
- A:所有功能都包含到Java 7中,发布推迟到2012年中旬
- B:不包含Project Lambda和Project Jigsaw等几个项目Java 7在2011年中旬发布,这几个项目推迟到2012年中旬发布的Java 8中
2012年7月 Mark Reinhold再次发文称Project Jigsaw将不会包含在Java 8中而得推迟到Java 9中,由此一来Java 8的主要特性就是Project Lambda。
2012年下旬->2013年下旬->2014年3月 Java 8的发布也是不断跳票。Project Coin、Collection Literals、Swing Date Picker等也被推迟到Java 9,而把Date & Time API、Nashorn等纳入Java 8中。
2014年3月18日 Java 8带着“即使有Bug也要发布”的节奏,历时2年8个月终于发布了。JavaTM SE 8 Release Contents
②关于Project Lambda
2005年,Java 6发布前很多人提议在Java中引入闭包Closure,先是Gilad Bracha、Neal Gafter、James Gosling、Peter van der Ahé做了一个Java闭包的提案,叫BGGA(以他们名字的首字母命名)、后来改名Closures for the Java Programing Language。关于这个提案在Java社区掀起了很到争论,Neal Gafter和Joshua Bloch争论最为有名。
除BGGA外,Java闭包的实现也有很多其他的方案,比如:Joshua Bloch、Doug Lea、Bob Lee提出了CICE(Concise Instance Creation Expresions)。还有一个提案是FCM(First Class Methods)。CICE并不是要在Java中引入闭包而是对匿名类做一个简化写法的提案(现在最终的Project Lambda也是很接近CICE)。
2008年在java.net做了一个在线调查,大概2000人参与回答,大部分人投给了BGGA或者干脆不引入闭包。
2008年11月,Mark Reinhold在 Devoxx 发布Java 7中不会引入闭包,从而才终止了这场争论。但是1年后的2009年11月Mark Reinhold同样是在 Devoxx 发布Java 7中要引入简单的闭包。基于此,2009年12月作为OpenJDK的子项目Project Lambda开始启动。
为什么2008年终止在Java 7中引入闭包会在2009年再次提出?
答案是:CPU多核化的趋势。无论是PC还是SmartPhone,CPU的多核化在急速发展,所以软件的并行处理也要跟得上。
Java中虽然可以通过Thread来并行处理,但是Java 5的Concurrency Utilities的处理粒度更大,而Java 7的Fork/Join Framework并行粒度更细。Java的for循环采用外部迭代(程序员自己写代码),需要转成内部迭代(由Java类库迭代)的并行化,而很多语言都已经支持内部迭代。虽然Java可以借助匿名类来实现,但是写法很繁琐,所以需要简化匿名类的写法。
2009年Project Lambda成立后,Mark Reinhold提出了一个原案Straw-Man Proposal。在这个稻草人提议中Mark Reinhold并没有使用以前争论不休的闭包,而是采用了Lambda表达式。基于此草案不断演化才得到了现在Java8的Lambda表达式。JSR 335: Lambda Expressions for the Java™ Programming Language:
接口的变化:
开始决定使用SAM(Single Abstract Method)来作为接口,SAM指只有一个方法的抽象类或接口。但函数型的引入又激起了争论,后来只限于接口,所以很少人再说SAM,而是引入了函数式接口的概念。
写法的变化:
#(参数) { 函数体 } -> (参数) -> { 函数体 }
Collections.xxxx() -> Stream API
实现的变化
匿名类 ->Java 7 引入的 InvokeDynamic命令动态生成Class
Project Lambda是一个漫长的过程,能够最终成行已经不易,看看这些人的名字,他们都是Java界的大神,尤其Doug Lea为Java并发做出了不可磨灭的贡献。
(2)Lambda表达式
λ:希腊字母表中排序第十一位的字母,英语名称为Lambda。最早出现是用于计算的λ演算(lambda calculus),后来被函数式编程语言广泛采用。
Lambda表达式可以理解成为是一个能够作为参数传递的匿名函数Object,他没有名字,但有参数列表、有函数体、有返回类型、可以抛出异常。它的类型,叫做“目标类型(target type)”Java8中就是“函数接口(functional interface)”。
语法:
引用
(parameters) -> expression
(parameters) -> statement
(parameters) -> { statements; }
(parameters) -> statement
(parameters) -> { statements; }
举例:
引用
() -> Math.PI * 2.0
(int i) -> i * 2
(String s) -> s.length()
(int i0, int i1) -> i0 + i1
(int x, int y) -> { return x + y; }
(int i) -> i * 2
(String s) -> s.length()
(int i0, int i1) -> i0 + i1
(int x, int y) -> { return x + y; }
①省略类型
(int x, int y) -> { return x + y; }; (x, y) -> { return x + y; };
***不能只省略一部分类型,比如:(int x, y) -> { return x + y; }; // NG
②1个参数可以省略括号
(String text) -> { System.out.println(text); }; (text) -> { System.out.println(text); }; text -> { System.out.println(text); };
***但是不能带类型,比如:String text -> { System.out.println(text); }; // NG
③函数体多行时需要大括号
(int i) -> { int prod = 1; for(int n = 0; n < 5; n++) prod *= i; return prod; };
④函数体只有一行的话可以省略大括号
text -> System.out.println(text);
***assert语句不能省略带括号,比如: s -> { assert !s.isEmpty(); };
***return语句不能省略带括号,比如:(x, y) -> return x -y; // NG
⑤只有一行代码而且有返回值的可以省略return,会返回该行代码计算结果
(x, y) -> { return x -y; }; (x, y) -> x -y;
***return要和大括号一起省略,比如:(x, y) -> { x - y; }; // NG
⑥没有参数没有返回值的空函数
() -> {};
⑦Scala等使用下划线做占位符,Java8中不可以
(_) -> System.out.println(_); // NG
⑧用于Lambda的变量不可变
int portNumber = 1337; Runnable r = () -> System.out.println(portNumber); // OK // 编译错误 // Local variable portNumber defined in an enclosing scope must be final or effectively final int portNumber = 1337; Runnable r = () -> System.out.println(portNumber); // NG portNumber = 1338; // 通过数组实现 final int[] wrappedNumber = new int[] { 1337 }; Runnable r = () -> System.out.println(wrappedNumber[0]); // OK wrappedNumber[0] = 1338;
⑨其他
- 一个λ表达式可以有多个目标类型(函数接口),只要函数匹配成功即可。但需注意一个λ表达式必须至少有一个目标类型。
- 一个λ表达式可以被当做Object使用,需要赋值给一个函数接口,然后再赋值给一个Object。
(3)Lambda和匿名类区别
this:匿名类this取得是自己,Lambda取得是所在的外部类。
public class LambdaTest { public LambdaTest() { Function func1 = new Function() { @Override public void func() { System.out.println("Anon Class: " + this.getClass()); } }; Function func2 = () -> System.out.println("Lambda Exp.: " + this.getClass()); } }
****但是很少需要在lambda中使用this
(4)用于何处
Lambda可以传递给任何希望是函数式接口的地方。
(5)运行机制
Java 7引入了invokedynamic指令,它是一个JVM指令,允许动态语言在run-time时动态绑定。Java 8的Lambda表达式并不是匿名类的语法糖,它不会在编译的时候生成类似于匿名类的xxx$1.class,而是在运行的时候使用invokeDynamic指令。对于一条Lambda表达式在class里边会包含一个invokedynamic命令和一个静态方法。运行时会使用LambdaMetafactory#metafactory做成一个Lambda$1的内部类再调用该函数式接口的实例。在运行时生成class,就是避免class太多影响加载速度,像Stream那样的到处是Lambda。
比如遍历List:
Arrays.asList("a", "b", "c").forEach(x -> System.out.println(x));
编译后的Class内容:
也可以接住异常堆栈信息看看Lambda是怎么执行的:
String[] datas = new String[]{""}; Arrays.asList(datas).stream().forEach(name -> check(name)); public static int check(String s) { if (s.equals("")) { throw new IllegalArgumentException(); } return s.length(); }
引用
Exception in thread "main" java.lang.IllegalArgumentException
at com.rensanning.java8.lambda.Test.check(Test.java:14)
at com.rensanning.java8.lambda.Test.lambda$0(Test.java:9)
at com.rensanning.java8.lambda.Test$$Lambda$1/518248.accept(Unknown Source)
at java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:948)
at java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:580)
at com.rensanning.java8.lambda.Test.main(Test.java:9)
at com.rensanning.java8.lambda.Test.check(Test.java:14)
at com.rensanning.java8.lambda.Test.lambda$0(Test.java:9)
at com.rensanning.java8.lambda.Test$$Lambda$1/518248.accept(Unknown Source)
at java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:948)
at java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:580)
at com.rensanning.java8.lambda.Test.main(Test.java:9)
参考:
http://www.oracle.com/events/us/en/java8/index.html
http://www.lambdafaq.org/
http://cr.openjdk.java.net/~briangoetz/lambda/lambda-translation.html
http://www.oracle.com/webfolder/technetwork/tutorials/obe/java/Lambda-QuickStart/index.html
http://www.dreamsyssoft.com/java-8-lambda-tutorial/index.php
http://www.slideshare.net/bitter_fox/java8-launch
http://www.slideshare.net/miyakawataku/lambda-meets-invokedynamic
http://cr.openjdk.java.net/~briangoetz/lambda/lambda-state-final.html
http://www.slideshare.net/mariofusco/fp-in-java-project-lambda-and-beyond
http://www.journaldev.com/2389/java-8-features-for-developers-lambdas-functional-interface-stream-and-time-api
- OReilly.Java.8.Lambdas.Mar.2014.rar (6 MB)
- 下载次数: 17
评论
2 楼
rensanning
2015-07-02
Function这里用的可能不恰当,但只是个示例,具体是Runnable 无参无返回;Supplier 无参有返回;Function 有参有返回。
1 楼
JimmyLincole
2015-07-02
Function func2 = () -> System.out.println("Lambda Exp.: " + this.getClass());
这一句应该是有问题的
一个是参数,一个是返回值
发表评论
-
Web API分页
2018-11-13 13:38 1504(一)分页类型 逻辑分页(客户端分页):从数据库将所有记录查询 ... -
JAXB实例入门
2017-06-09 10:17 1703JAXB(Java Architecture for XML ... -
Java Web项目中的Event
2017-06-05 09:42 1612(1)Servlet的事件和监听器 *** Servle ... -
关于Java SPI
2017-05-04 12:07 1986SPI:Service Provider Interface ... -
Jackson实例入门
2017-05-03 12:55 1636Jackson:Java平台的JSON解析器。 版本: ja ... -
为什么https被redirect成了http?
2016-11-14 09:35 7638全站HTTPS并不是配置证书CA,改改路径URL那么简单! ... -
简化Java代码
2016-10-09 11:25 1247样板代码Boilerplate Code的 ... -
Java Web Project based on Spring
2016-09-28 11:21 985基于Spring开发Web项目的标配Library。 工具 ... -
Eclipse Scrapbook快速测试Java代码
2016-09-09 15:12 1276Scrapbook是Eclipse提供的特 ... -
Java爬取 百度图片&Google图片&Bing图片
2016-08-04 09:54 7455先看看抓取的结果。 抓关键字“美女”的百度图片: 抓关键字 ... -
学习Java容易混淆的一概念
2016-05-13 11:01 1607基础篇 (1)== vs equals() ... -
20年Java发展历程(1995-2015)
2015-03-25 21:58 2275Java语言作为现在最流行的编程语言之一,它已经经历了整整20 ... -
Java命令行选项解析之Commons-CLI & Args4J & JCommander
2014-11-27 12:09 22380熟悉Linux命令的都知道几乎所有程序都会提供一些命令行选项。 ... -
Java调用Native API之JNA
2014-11-10 12:09 7712Java调用C/C++的Native API一般采用JNI(J ... -
Java执行SSH/SCP之JSch
2014-08-27 17:17 11422JSch (Java Secure Channel)是纯Jav ... -
GC日志分析
2014-07-18 08:54 2821GC:Garbage Collection 垃圾回收 (1) ... -
Java元组类型之javatuples
2014-05-20 10:58 26915关于方法的返回值,经常需要返回2个值或多个值的一个序列,比如数 ... -
Java 8 之 反编译Lambda表达式(CFR)
2014-04-14 09:34 6471CFR(Class File Reader) - anoth ... -
Java 8 之 Optional类
2014-04-08 14:38 2931在Java中,null代表一个不存在的对象,如果对它进行操作就 ... -
Java交互模式执行代码 之 Java REPL
2014-03-27 14:58 3265REPL(Read-Eval-Print-Loop)即“读取- ...
相关推荐
Java8的lambda表达式
java8lambda表达式的安卓Studio工程Demo,供初步学习使用
主要内容: ● 为何需要lambda,...第2章 Java lambda表达式的基础知识 23 第3章 流与管道介绍 55 第4章 终止流:收集与汇聚 91 第5章 起始流:源与分割迭代器 135 第6章 流的性能 167 第7章 使用默认方法演化API 195
视频地址:https://www.bilibili.com/video/BV1ut411g7E9 【Java8】Lambda表达式 和 Stream API 详解笔记 md文档
本文通过示例大家给大家介绍了java8之lambda表达式的基本语法,感兴趣的的朋友一起看看吧
java lambda表达式,lambda 表达式基本上表达了函数式接口的实例(具有单一抽象方法的接口称为函数式接口。一个例子是 java.lang.Runnable)。lambda 表达式实现了唯一的抽象函数,因此实现了函数式接口 lambda ...
说明:本文档主要讲解java8中的Lambda表达式。内容完全基于java 8 tutorial,加上一些自己的注释与理解。使用代码本身来进行解释(这是java 8 tutorial中的风格),同时去掉一些无关紧要的知识点(比如泛型等),...
关于Java中lambda的表达式,Java多核编程,清华大学(出版)
Java 8 在 2013 年发布,Java 8 将支持 Lambda 功能,尽管该规范还在不断的变化,但是 Java 8 的开发版已经实现了对 lambda 的支持。
1、Lambda表达式概述:了解Lambda表达式的定义、语法和变量捕获机制,以及为什么要在Java中引入Lambda表达式来支持函数式编程。 2、函数式接口与Lambda表达式:学习如何使用Lambda表达式与不同类型的函数式接口进行...
java8-lambda表达式的基础使用.pdf
主要介绍了java8之lambda表达式用法总结,需要的朋友可以参考下
NULL 博文链接:https://shmilyaw-hotmail-com.iteye.com/blog/2251821
JAVA 8 Lambda表达式-Lambda Expressions.rar
本篇文章主要介绍了30分钟入门Java8之lambda表达式学习,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
java lambda 表达式中文详解(语言篇和类库篇),更方便更快捷了解java lambda表达式
这个是专门介绍java 8 lambda表达式的一本书,目前没有中文版的,这个是英文版的。
lambda表达式是JAVA8中提供的一种新的特性,它支持Java也能进行简单的“函数式编程”。 下面这篇文章主要给大家介绍了关于Java8新特性Lambda表达式的一些复杂用法的相关资料,需要的朋友可以参考借鉴,下面来一起看...
Java8发布到现在至少3年了,但是对Lambda表达式不熟悉、看不懂、不会用的现象非常常见。 即使是升级到JDK1.8了,但是很多开发者依然是停留在1.8之前的开发方式,使用的也是非常老旧和过时的API,遇到函数式接口也是...
Stream、Lambda表达式练习.doc