java1.8 lambda表达式 函数式编程 闭包
来源:互联网 发布:阿里云测试培训 编辑:程序博客网 时间:2024/05/16 05:29
java1.8出来好久一直没怎么关注。这段时间公司的项目数据处理,需要频繁操作集合,用for遍历集合做计算,感觉很费劲,而且有大量重复代码。可读性也不高。这时候想到java1.8新特性之一:函数式编程
一、函数式接口 (functional interface)
@FunctionalInterfaceinterface DoSomeThing { int getAge(int a, int b); static void getName() { System.out.println("函数式接口的静态方法"); } default void getAge() { System.out.println("函数式接口的默认方法"); }}
如果一个方法接受一个函数式接口作为参数,那么我们可以传入以下类型作为参数:
- 匿名内部类(Anonymous Inner Class)(Java的以前版本中经常使用的方式,在Java 8中不再被推荐)
- Lambda表达式
- 方法或者构造器的引用(Method or Constructor Reference
二、闭包(closure)(回顾)
lambda表达式大量用到了闭包和函数回调,java1.8之前不支持显性闭包,要实现代码片段的传递,只能通过内部类的方式,模拟闭包。
闭包简而言之就是 含有状态的函数。
在java语言中,闭包的应用:一个代码段被用来做为方法的参数.
java中没有直接使用某个方法做为另一个方法的参数的,java使用匿名内部类来模拟这种情况。
比如一个二元函数 f _x,y,x,y是函数内部使用的变量,在只给定 一个参数 x = 7 的情况下, x 已经绑定,但是y还是自由的,这个时候 f(7, y) 就相当于含有一个私有变量(x=7)的函数了。当再给定另外一个变量 y 的值就可对函数完整的求值。所以函数中 有的参数是绑定的,有的参数自由的,这样的机制称为闭包。
闭包的价值在于可以作为函数对象或者匿名函数,持有上下文数据,作为第一级对象进行传递和保存。闭包中的部分变量没有在引用者的作用域内声明,对于引用者这些变量就是自由变量。java中能够保存方法的变量指的就是普通的对象。Java最常用的闭包实现办法(内部类+接口)。通俗点讲:内部类的方法既能引用宿主的私有变量,又能传入主动调用者的变量(包括 指向对象(该对象可以抽象出接口:自定义回调函数)的变量),该内部类也可抽象出接口便于扩展。内部类的模拟闭包机制还实现了窥内的效果。
由于闭包上下文中有引用指向了内部类的宿主,所以宿主对象在没有其他引用的情况下也不会被销毁,只有该闭包中的回调函数执行完,才会被GC回收。
[注:在A作用域中使用的变量x(A一般为主线程的方法,主动调用者),却没有在A作用域中声明(即在其他作用域中声明的),对于A作用域来说,x就是一个自由变量],比如fun(x,y){},x和y是函数自己定义的,就不是自由变量,如果x是使用其他函数定义的,就是自由变量
总结:了解完闭包之后,我们知道在java1.8中不需要用内部类的方式实现闭包。
Lambda表达式会被编译器转换成相应函数式接口的一个实例,它表达式提供了一个上下文环境,既能引用该实例作用域的变量,又可以引用主程序所在作用域的所有变量。这种效果就是闭包,该实例中的变量就是自由变量。
闭包就是一个函数引用另外一个函数的变量,因为变量被引用着所以不会被回收,因此可以用来封装一个私有变量。这是优点也是缺点,不必要的闭包只会徒增内存消耗
http://blog.csdn.net/hnust_xiehonghao/article/details/46326997
根据groovy中的闭包来理解
一个groovy闭包就像一个代码块或者方法指针,他是定义然后执行的一段代码,但是他有一些特性:隐含变量,支持自由变量,支持currying 。
我们先来看看一些例子:
1
def
clos = {
println
"hello!"
}
2
3
println
"Executing the Closure:"
4
clos()
//prints "hello!"
在上面的例子中”hello!”是因为调用clos()函数才打印出来的,而不是在定义的时候打印出来的。
参数
闭包的参数在->之前列出,比如:
1
def
printSum = { a, b ->
print
a+b }
2
printSum(
5
,
7
)
//prints "12"
如果闭包的参数是少于2个的话,那么 ->是可以省略的。
Parameter notes
A Closure without -> , i.e. {} , is a Closure with one argument that is implicitly named as ‘it’. (see below for details) In some cases, you need to construct a Closure with zero arguments, e.g. using GString for templating, defining EMC Property etc. You have to explicity define your Closure as { -> } instead of just { }
You can also use varargs as parameters, refer to the Formal Guide for details. A JavaScript-style dynamic args could be simulated, refer to the Informal Guide.
自由变量
闭包能引用在参数列表中没有列出的变量,这些变量成为自由变量,他们的作用范围在他们定义的范围内:
1
def
myConst =
5
2
def
incByConst = { num -> num + myConst }
3
println
incByConst(
10
)
// => 15
另外一个例子:
1
def
localMethod() {
2
def
localVariable =
new
java.util.Date()
3
return
{
println
localVariable }
4
}
5
6
def
clos = localMethod()
7
8
println
"Executing the Closure:"
9
clos()
//prints the date when "localVariable" was defined
隐式变量
it
如果你有一个闭包但是只有一个参数,那么你可以省略这个参数,比如:
1
def
clos = {
print
it }
2
clos(
"hi there"
)
//prints "hi there"
- java1.8 lambda表达式 函数式编程 闭包
- Java1.8新特性 Lambda/Stream/函数式编程
- 函数式编程 Lambda表达式
- AndroidStudio配置支持java1.8lambda表达式
- java1.8 lambda表达式初识(一)
- java1.8 lambda表达式语法(二)
- java 8函数式编程与Lambda表达式
- Java 8 函数式编程(Lambda 表达式)
- 用Lambda表达式进行函数式编程
- Java8 Lambda表达式 函数式编程
- java函数式编程之lambda表达式
- 函数式编程--使用lambda表达式
- 函数式编程—初识Lambda表达式
- Java8 Lambda表达式 函数式编程
- Java8:函数式编程与Lambda表达式
- Java8 Lambda表达式 函数式编程
- Java函数式编程与Lambda表达式
- 函数式编程初步(lambda表达式)
- mySql的连接useSSL=false
- android 应用重启实现
- pandas.DataFrame.append
- 员工部门mysql面试题
- 单片机与数字电路抗干扰措施
- java1.8 lambda表达式 函数式编程 闭包
- Canvas基础知识
- C++中的Compare()函数用法
- Android工程方法数超过65535,怎么破
- 赫夫曼编码
- 重新搭建eclipse、android、tomcat平台
- Android 仿火萤视频桌面 神奇的LiveWallPaper
- hadoop部署参考
- Git命令