Java8之旅(六) -- 使用lambda实现尾递归
前言
本篇介绍的不是什么新知识,而是对前面讲解的一些知识的综合运用。众所周知,递归是解决复杂问题的一个很有效的方式,也是函数式语言的核心,在一些函数式语言中,是没有迭代与while这种概念的,因为此类的循环通通可以用递归来实现,这类语言的编译器都对递归的尾递归形式进行了优化,而Java的编译器并没有这样的优化,本篇就要完成这样一个对于尾递归的优化。
什么是尾递归
本篇将使用递归中最简单的阶乘计算来作为例子
递归实现
/**
* 阶乘计算 -- 递归解决
*
* @param number 当前阶乘需要计算的数值
* @return number!
*/
public static int factorialRecursion(final int number) {
if (number == 1) return number;
else return number * factorialRecursion(number - 1);
}
这种方法计算阶乘比较大的数很容易就栈溢出了,原因是每次调用下一轮递归的时候在栈中都需要保存之前的变量,所以整个栈结构类似是这样的
5
4
3
2
1
------------------->
栈的深度
在没有递归到底之前,那些中间变量会一直保存着,因此每一次递归都需要开辟一个新的栈空间
尾递归实现
任何递归的尾递归版本都十分简单,分析上面栈溢出的原因就是在每次return的时候都会附带一个变量,因此只需要在return的时候不附带这个变量即可。说起来简单,该怎么做呢?其实也很容易,我们使用一个参数来保存上一轮递归的结果,这样就可以了,因此尾递归的阶乘实现应该是这样的代码。
/**
* 阶乘计算 -- 尾递归解决
*
* @param factorial 上一轮递归保存的值
* @param number 当前阶乘需要计算的数值
* @return number!
*/
public static int factorialTailRecursion(final int factorial, final int number) {
if (number == 1) return factorial;
else return factorialTailRecursion(factorial * number, number - 1);
}
使用一个factorial变量保存上一轮阶乘计算出的数值,这样return的时候就无需保存变量,整个的计算过程是
(5*4)20 -> (20*3) 60 -> (60*2) 120 -> return 120
这样子通过每轮递归结束后刷新当前的栈空间,复用了栈,就克服了递归的栈溢出问题,像这样的
return
后面不附带任何变量的递归写法,也就是递归发生在函数最尾部,我们称之为'尾递归'。
使用lambda实现编译器的优化
很显然,如果事情这么简单的话,这篇文章也就结束了,和lambda也没啥关系
Java8之旅(六) -- 使用lambda实现尾递归的更多相关文章
- Java8函数之旅 (六) -- 使用lambda实现Java的尾递归
前言 本篇介绍的不是什么新知识,而是对前面讲解的一些知识的综合运用.众所周知,递归是解决复杂问题的一个很有效的方式,也是函数式语言的核心,在一些函数式语言中,是没有迭代与while这种概念的,因为此类 ...
- Java8之旅(七) - 函数式备忘录模式优化递归
前言 在上一篇开始Java8之旅(六) -- 使用lambda实现Java的尾递归中,我们利用了函数的懒加载机制实现了栈帧的复用,成功的实现了Java版本的尾递归,然而尾递归的使用有一个重要的条件就是 ...
- 开始Java8之旅(四) --四大函数接口
前言 Java8中函数接口有很多,大概有几十个吧,具体究竟是多少我也数不清,所以一开始看的时候感觉一脸懵逼,不过其实根本没那么复杂,毕竟不应该也没必要把一个东西设计的很复杂. 几个单词 在学习 ...
- Java8学习之旅2---基于Lambda的JDBC编程
Java8的Lambda表达式确实是一个很好的特性.可是在哪些场合下使用.事实上还是须要细致考虑的.我们当然不能为了使用而使用,而是须要找到切实实用的场合.在JDBC编程中,比如查询语句,首先须要进行 ...
- java8新特性1:lambda表达式和函数式接口
1.lambda的介绍: 1.1.为什么java语言需要引入lambda表达式? java语言诞生于1995年,历史时间已经相对较长了.在其后的各种新型编程语言中,都有着lambda表达式的内容,并且 ...
- Java8之——简洁优雅的Lambda表达式
Java8发布之后,Lambda表达式,Stream等等之类的字眼边慢慢出现在我们字眼.就像是Java7出现了之后,大家看到了“钻石语法”,看到了try-with-resource等等.面对这些新东西 ...
- java8 新特性入门 stream/lambda
Java 8 中的 Stream 是对集合(Collection)对象功能的增强,它专注于对集合对象进行各种非常便利.高效的聚合操作(aggregate operation),或者大批量数据操作 (b ...
- Java8新特性之一:Lambda表达式
Java8是自java5之后最重大的一次更新,它给JAVA语言带来了很多新的特性(包括编译器.类库.工具类.JVM等),其中最重要的升级是它给我们带来了Lambda表达式和Stream API. 1. ...
- java8 学习之路之lambda
前言 目前我们知道java的版本已经发布到12了,之前的项目用的是JDK1.7,听说JDK1.8的改动相对来说大一些,因此抽空学学JDK1.8的一些新特性.本人也是通过阅读Java8实战这本书做一些小 ...
随机推荐
- 201521123104《Java程序设计》第1周学习总结
1. 本章学习总结 1.初步了解了什么是Java,以及该如何编写简单的Java程序: 2.认识到相比于C和C++来说,Java更复杂一些,所以学习要花费更大的精力: 3.在编写Java程序过程中,认识 ...
- JAVA课程设计个人博客 学生成绩管理 201521145048 林健
1. 团队课程设计博客链接 http://www.cnblogs.com/kawajiang/p/7062407.html 2.个人负责模块或任务说明 本人主要负责支持用户登录.验证操作,显示设计界面 ...
- 201521123067 《Java程序设计》第12周学习总结
201521123067 <Java程序设计>第12周学习总结 1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多流与文件相关内容. 2. 书面作业 将Student对 ...
- YYHS-鏖战字符串
题目描述 Abwad在nbc即将完成她的程序的时候,急中生智拔掉了她电脑的电源线,争取到了宝贵的时间.作为著名论文<论Ctrl-C与Ctrl-V在信息学竞赛中的应用>的作者,他巧妙地使用了 ...
- 作为一个新人,怎样学习嵌入式Linux
作为一个新人,怎样学习嵌入式Linux?被问过太多次,特写这篇文章来回答一下. 在学习嵌入式Linux之前,肯定要有C语言基础.汇编基础有没有无所谓(就那么几条汇编指令,用到了一看就会). C语言要学 ...
- HDFS的web接口
50070端口查看NameNode状态,该端口的定义位于core-default.xml中,可以在core-site.xml中自行修改. 50075端口查看DataNode的,该地址和端口的定义位于h ...
- 导出含有图片的Java项目,图片不显示
项目的一些图片资源文件在导出成JAR包后,无法正确读取虽然Java项目还是可以运行,但原来的图片资源全不见了,于是你可以打开JAR包看看里面的东西,确实是有图片在里面,就是无法读取. 其实是因为我们在 ...
- ssl协议以及生成
一.https协议https是一安全为目标的httpt通道,简单讲师http的安全版.即http下加入ssl层,https的安全基础是ssl,因此加密的详细内容就需要ssl.http和https的区别 ...
- bzoj 3212 Pku3468 A Simple Problem with Integers
3212: Pku3468 A Simple Problem with Integers Time Limit: 1 Sec Memory Limit: 128 MB Description You ...
- FastDFS安装步骤
FastDFS是用c语言编写的一款开源的分布式文件系统,充分考虑了冗余备份.负载均衡.线性扩容等机制,并注重高可用.高性能等指标,使用FastDFS很容易搭建一套高性能的文件服务器集群提供文件上传.下 ...