java 递归与迭代_java中堆栈区别,递归和迭代区别

本文探讨了在遍历文件夹时,深度优先搜索(DFS)方法可能导致栈溢出的问题。当路径深度超过一定数量时,递归实现的DFS会消耗大量栈空间,引发StackOverflowError。相比之下,使用迭代和栈来实现DFS可以避免这个问题,因为迭代主要使用堆空间,其空间限制较大。同时,文章解释了堆和栈的区别,以及递归和迭代在内存使用上的差异,指出迭代不会导致栈溢出,而可能导致堆溢出(OOM)异常。
摘要由CSDN通过智能技术生成

1. 读取某个文件夹下的文件

采用深度优先的方法,遍历文件夹,有文件就进行文件操作。

深度优点方法:使用递归实现;

private voidrecursion (Path path) {

FileStatus[] children=fs.listStatus (path);for(FileStatus child : children){if(child.isDir()){

recursion(child.getPath());

}else{

……//执行文件处理代码

}

}

}

注意:当路径深度很少的时候这样的方法不存在问题,但是如果路径大于100+,就会出现栈溢出的错误。

Why?

换成迭代实现

Stack pathstack = new Stack();for(pathstack.push(fs.getFileStatus(path)); !pathstack.empty();){

FileStatus cur=pathstack.pop();

FileStatus[] children=fs.listStatus(cur.getPath());for(int i = 0; i < children.length; i++) {final FileStatus child =children[i];if(child.isDir()) {

pathstack.push(child);

}else{

……//执行文件处理代码

}

}

}

问题消失了~~Why?

2. 堆和栈的区别

堆是有序完全二叉树,栈是一种先进后出的线性表,栈的特点是速度快,jvm的压栈和出栈操作都是非常高效的(相对来说,堆的二叉树遍历是要比先进后出线性表要慢的)。

每一个Java应用都唯一对应一个JVM实例,每一个实例唯一对应一个堆,对象的大小是不可估计的,是动态的。

对象的应用却放在栈中,一个对象对应了一个4btye的引用。

3. 递归和迭代的区别

递归是通过一个函数进行的,函数使用了栈空间存放在函数中申明的基本数据类型(例如int,char)和堆中对象的引用(注意是引用,而非对象本身)。所以递归由于不断调用自身函数体,因此会导致需要使用的栈空间不断增加,最终导致栈溢出。

迭代是在一个函数中的循环体,迭代使用的pathstack这个变量,在JVM栈中只有一个4字节的指针(引用的本质),而变量的主体本身使用的则是堆内存空间。

堆空间相对于栈空间来说要大得多,但是如果无限制的使用堆空间,当然也会溢出,这就是java程序员都经常会遇到的OOM(OutOfMemoryError)异常。OOM异常是非常常见的堆溢出,而StackOverFlow这个栈溢出异常则非常少见,如文章所言,栈中只存放一些4字节的指针,所以虽然栈空间很小,但想撑爆栈空间也不是那么容易的事情,这就是为什么本地应用很难遇到栈溢出的原因。

递归就是在过程或函数里面调用自身,而迭代是利用变量的原值推算出变量的一个新值。如果递归是自己调用自己的话,迭代就是A不停的调用B。显然递归用了栈空间,迭代因为始终在一个函数体中,所以使用的是堆空间。迭代只会导致堆溢出(OOM)而不会导致栈溢出。

迭代不会使用栈空间,所以当然不会导致栈溢出。Stack类的实例变量因为使用的内存空间是处于堆空间中,因此当然可以避免栈溢出。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值