- 浏览: 380098 次
- 性别:
- 来自: 杭州
-
文章分类
最新评论
-
真的全站唯一:
描述的能不能准确一点,我也以为bigDecimal性能比dou ...
【性能】Java BigDecimal和double性能比较 -
zhanggang807:
学习到了。。以后会考虑往这方面设计
【java规范】Java spi机制浅谈 -
Xiong506:
xiyuan1025 写道你这是在linux下吗,我在linu ...
[监控]Btrace监控简单笔记 -
Xiong506:
xiyuan1025 写道你这是在linux下吗,我在linu ...
[监控]Btrace监控简单笔记 -
Bll:
找不到实现类
【java规范】Java spi机制浅谈
现象 :
递归是我们很经典的一种算法实现,可以很好的描述一个算法的原理!对于算法的描述、表现和代码结构理解上,递归都是不错的选择!
但是本文想说的是java实现一个递归算法的时候尽量不要用递归实现,而是转换成的非递归实现。
最近在实现一个比较复杂算法的时候,尝试了一下,非递归实现相比递归实现速度上能提升1/3。
以下面一个简单的例子来说:
(注:为了描述简单,所以这里只用一个简单的例子。这个例子可以用更简单的数学公式来实现,所以请大家不要过分在意。 重点是想说明递归可能带来的一些问题)
输入参数:N
输出结果: log1+log2+log3+....+logN
两种实现代码如下:
package test; public class RecursiveTest { /** * 递归实现 * * @param n * @return */ public static double recursive(long n) { if (n == 1) { return Math.log(1); } else { return Math.log(n) + recursive(n - 1); } } /** * 非递归实现 * * @param n * @return */ public static double directly(long n) { double result = 0; for (int i = 1; i <= n; i++) { result += Math.log(i); } return result; } public static void main(String[] args) { int i = 5000000; long test = System.nanoTime(); long start1 = System.nanoTime(); double r1 = recursive(i); long end1 = System.nanoTime(); long start2 = System.nanoTime(); double r2 = directly(i); long end2 = System.nanoTime(); System.out.println("recursive result:" + r1); System.out.println("recursive time used:" + (end1 - start1)); System.out.println("non-recursive result:" + r2); System.out.println("non-recursive time used:" + (end2 - start2)); } }
得到运行结果如下:
recursive result:7.212475098340103E7
recursive time used:539457109
non-recursive result:7.212475098340103E7
non-recursive time used:282479757
可以看出递归的运行时间是非递归运行时间将近2倍。
(注:以上代码还是在-Xss200m的参数下运行的,如果栈空间不足,直接不能运行)
原因简单分析:
上图是java线程栈的结构。java将为每个线程维护一个堆栈,堆栈里将为每个方法保存一个栈帧,栈帧代表了一个方法的运行状态。 也就是我们常说的方法栈。最后一个为当前运行的栈帧。
那么每一次方法调用会涉及:
1.为新调用方法的生成一个栈帧
2.保存当前方法的栈帧状态
3.栈帧上下文切换,切换到最新的方法栈帧。
递归实现将导致在栈内存的消耗(往往需要调整Xss参数)和因为创建栈帧和切换的性能开销,最终大大的影响效率!
所以,如果你想提升你的算法效率,不要使用递归实现是一个基础原则!
另外,递归是我们用来理解算法的一个方法,当用代码来实现的时候基本都可以转换成非递归的代码实现!
评论

向楼上所说递归是用来简单化来表达数据处理的思想
要是不用递归试试计算 f(n)=f(n-1)+f(n-2)+f(n-3)+f(n-4)+f(n-5)
不管是用非递归或推数学公式(上面公式已经要计算一元五次方程的解了),会非常复杂
五次方程没有根式解,
手工计算5个根有点累。
计算机计算起来比较容易。
可以考虑用演化计算,选择一个比较好的算子,很快就能算出最优解
for
for
for
......
结果以参数的形式传递,这样可以省去递归由于要保存栈信息而带来的开销。
如果要做一些可扩展的组件,递归是不可避免的.
不会递归可耻;滥用递归也可耻;不会正确的使用递归同样可耻。
但如果迭代次数过多的话,会影响性能
空间消耗代价
recursive result:7.212475098340103E7
recursive time used:312802755
non-recursive result:7.212475098340103E7
non-recursive time used:312842609
JDK 对尾递归还是会自己做优化的

向楼上所说递归是用来简单化来表达数据处理的思想
要是不用递归试试计算 f(n)=f(n-1)+f(n-2)+f(n-3)+f(n-4)+f(n-5)
不管是用非递归或推数学公式(上面公式已经要计算一元五次方程的解了),会非常复杂
你根本就不理解本帖子要说明什么! 只是想说明递归的开销!
例子不是最重要的,"除非疯子才一个一个算logx相加 ....... "这个大家都懂得,不要过分去在意这个。

向楼上所说递归是用来简单化来表达数据处理的思想
要是不用递归试试计算 f(n)=f(n-1)+f(n-2)+f(n-3)+f(n-4)+f(n-5)
不管是用非递归或推数学公式(上面公式已经要计算一元五次方程的解了),会非常复杂
五次方程没有根式解,
手工计算5个根有点累。
计算机计算起来比较容易。
你确定无解?只是无代数根式解
五次方程符合Galois群理论,就可以有解。。。。(x-a)(x-b)(x-c)(x-d)(x-e)=0 a,b,c,d,e都不相等,这个五次方,你说有解吗?
发表评论
-
Xml ResourceBundle简单实现
2012-04-17 21:45 4504ResourceBundle主要是用于和本地语言环境相关的一些 ... -
【maven】多子模块maven模板工程archetype创建过程
2012-04-02 20:55 17728最近项目里需要创建一 ... -
【java基础】如何设计java应用程序的平滑停止
2012-03-05 23:44 11043java应用程序退出的触发机制有: 1.自动结束:应用没有存 ... -
【java并发】juc Executor框架详解
2012-02-26 13:55 12609Executor 框架是 juc 里提供的线程池的实现。 ... -
【java并发】juc高级锁机制探讨
2012-02-23 00:52 8790最近在看一些j ... -
【java并发】基于JUC CAS原理,自己实现简单独占锁
2012-02-14 13:47 7900synchronized的基本原理回 ... -
[NoSQL]MongoDB初体验
2012-01-05 16:06 3993因为未来业务发展的一 ... -
【JVM】HotSpot JVM内存管理和GC策略总结
2011-12-13 22:05 16004JVM的相关知识是学习java ... -
32位机器下的一个java.lang.OutOfMemoryError错误分析
2011-10-17 11:19 2621昨天在本人windows机器( ... -
[监控]Btrace监控简单笔记
2011-09-09 10:57 5113前阵子看了公司网站的一个cache 命中率统计的btrace监 ... -
DBCP数据源配置项记录
2011-09-01 20:22 3018网站最近发生了数据库连接爆掉的问题。排查了下各个应用存在 ... -
【性能】Java BigDecimal和double性能比较
2011-08-28 20:06 14289我们知道 java 里面有个 BigDecimal ... -
【Spring】IOC容器并发条件下,可能发生死锁
2011-08-28 17:07 69661.背景 上周在生产环境应用启 ... -
JDK7 AIO 初体验
2011-08-17 19:20 2626JDK7 AIO初体验 JDK7已经releas ... -
java日志,需要知道的几件事(commons-logging,log4j,slf4j,logback)
2011-02-28 17:12 46536java日志,需要知道的几件事 如果对于comm ... -
JVM问题诊断常用命令:jinfo,jmap,jstack
2010-08-17 17:55 125351.jinfo 描述:输出给定 java ... -
java 浮点数为什么精度会丢失
2010-07-15 22:30 4972由于对float或double 的使用不当,可能会出现精度 ... -
一个枚举类的方法设计
2010-06-21 15:28 1736public enum ActionType { A ... -
java内部字符编码浅析
2010-06-07 21:43 6889java内部字符编码浅析 本周遇到一个 ... -
JDK反射之JDK动态proxy
2010-06-07 21:27 4149JDK动态代理 JDK 动态代理是 java 反射的一 ...
相关推荐
为什么使用二叉树? 树的术语 一个类比 二叉搜索树如何工作 查找节点 插入一个节点 遍历树 查找最大值和最小值 删除节点 二叉树的效率 用数组表示树 重复关键字 完整的tree.java程序 哈夫曼(Huffman)编码 小结 问题 ...
7. **慎用`synchronized`**:同步可能导致性能下降,尽量缩小同步范围,使用同步方法代替同步代码块。 8. **避免`finalize`方法**:`finalize`方法执行时机不确定,不利于资源清理。建议使用`try-finally`或`try-...
递归方法简单直观,但需要注意的是,递归算法可能会因为调用栈过深导致栈溢出,尤其在处理大数据量时要慎用。 素数判断问题则考察了面试者对基本算法的理解。素数是只有1和它本身两个因子的自然数。在编写程序判断...
#### 六、慎用`static`变量 `static`变量在整个类的生命周期中只有一份副本,虽然可以共享,但容易成为内存泄漏的源头。除非必要,应优先考虑使用`final`修饰的类内私有常量,这样既能保持不变性,又可避免潜在的...
5.5.1 慎用字符的Unicode转义形式 5.5.2 中止行注释的转义字符 5.6 泛型可能引起的错误 5.6.1 原始类型变量的赋值 5.6.2 原始类型带来的擦除 5.6.3 创建泛型数组的陷阱 5.7 正则表达式的陷阱 5.8 多线程的...
2.1.1只使用非递归的mutex . . . . . . . . . . . . . .. . . . . . . . . . 33 2.1.2死锁. . . . . . . . . . . . . . . . . . . .. . . . . . . . . . . . . . 35 2.2条件变量(condition variable). . . . . . ....