Java 递归和循环哪个更有效?

Java 递归和循环哪个更有效?,java,loops,recursion,performance,Java,Loops,Recursion,Performance,我很好奇哪一种迭代更有效。我正在使用一个函数将一个字符串分解为一个列表。递归是CPU效率更高还是循环?两者都是内存效率更高的吗?通过循环,我指的是for、for-each、do-while、while和任何其他类型。在这些循环中,哪一个更有效?或者他们都是平等的?只是好奇。迭代通常会更有效率。递归需要更多的内存(设置堆栈帧)和时间(相同)。但是,如果您可以设置尾部递归,编译器几乎肯定会将其编译为迭代或类似的内容,从而使您具有递归的可读性优势,并具有迭代方法的性能 在某些情况下,迭代解决方案将通过

我很好奇哪一种迭代更有效。我正在使用一个函数将一个字符串分解为一个列表。递归是CPU效率更高还是循环?两者都是内存效率更高的吗?通过循环,我指的是for、for-each、do-while、while和任何其他类型。在这些循环中,哪一个更有效?或者他们都是平等的?只是好奇。

迭代通常会更有效率。递归需要更多的内存(设置堆栈帧)和时间(相同)。但是,如果您可以设置尾部递归,编译器几乎肯定会将其编译为迭代或类似的内容,从而使您具有递归的可读性优势,并具有迭代方法的性能

在某些情况下,迭代解决方案将通过基本上维护自己的堆栈来实现,因此差异可能最小


有关更多详细信息,请参阅。

某些情况更适合递归……而其他情况更适合简单迭代。例如,导航目录优于递归。其他树结构也是如此。然而,递归使用更多的内存。对于迭代简单列表(如字符串),迭代(循环)更有效

你不能就此作一般性的陈述。这取决于循环在做什么,你如何编码它。。。以及JIT编译器能够如何优化它。它还可以改变循环迭代的列表类型。递归也是如此

为了得到可靠的答案,您需要逐个检查各种备选方案,并(小心地!)在Java平台上对特定示例进行基准测试

Java中的递归存在一个问题,即每一级递归都需要一个堆栈框架,Java堆栈的大小是有限的。如果您必须递归太深,您的算法将崩溃,出现
stackoverflowerrror
。(当前一代Java平台不实现尾部调用优化。)

您还希望避免在
LinkedList
上执行基于索引的迭代(例如,对于i=0到大小-1的
),因为这将为您提供
O(N^2)
行为



幸运的是,不同类型的Java循环的性能差异通常不会产生足够的影响。因此(将堆栈深度问题和选择正确的
列表
类的问题进行模块化),您可以安全地将性能留给“以后”。。。当且仅当有必要进行性能优化时才进行处理。

根据我的说法,对您的问题最好的回答是“视情况而定”:

平均而言,递归在搜索已排序的集合时要快得多,因为您可以使用“分而治之”之类的算法(在本例中,将集合分为两部分,并将元素所在的位置的一半发送到递归的下一步。当元素被找到或不包含在集合中时,递归停止)

然而,在大多数情况下,循环比递归更有效,因为一个简单的事实是,当在不同级别的递归中运行时,CPU在堆栈中保留变量,这基本上填满了堆栈。循环只在堆栈中使用恒定的空间(通常,但例外情况适用)。例如,如果您是使用递归算法计算斐波那契序列的专家,则在斐波那契(30)之后需要几年才能得到结果。该序列可以通过记忆(基本上使用循环)进行计算

要记住的一件事是递归比循环更容易理解,也更容易帮助解决问题。许多基于循环的问题解决方案都是从一个递归算法(分治)开始的,该算法在循环算法(记忆化)中得到优化。我上了一堂关于这个主题的课,它非常有趣

希望我能帮忙


关于。

在我的选择中,循环更好,递归将具有函数调用跟踪,这将占用更多内存。这同样取决于功能。我同意其他海报,因为它实际上取决于你正在解决的问题。我个人的偏好是通常避免递归,因为它可能更难维护与迭代相比,在调试中,可能会进行调试,这取决于实现者或维护者的技能(谁是较弱的环节)。但是,没有提到的一项是一些新的Java线程功能(例如ForkJoinPool)一个递归的解决方案很容易被做成一个多线程的线程,而java中的线程是困难的,但是如果在线程中分配工作负载,这是一个需要考虑的问题。这种类型的特性是有用的。

< P>我已经创建了两个微基准,它们测量递归与循环性能。它们都在随机数据集上执行计算,以避免JIT欺骗

在第一种情况下,我计算一个随机整数矩阵中的单元格之和。当矩阵的边等于60时,递归比循环慢10倍

在第二种情况下,我通过生成斐波那契数来比较递归和递归模拟。递归模拟是GC友好的-在计算过程中没有内存分配。在这种情况下,递归在“较小”的情况下快2倍,在计算量较大的情况下快5倍

所以归根结底,Java中的递归非常有效,尽管不像循环那样有效

Environment:
OS: Windows 8 6.2, Core i5
JVM: Oracle Corporation Java HotSpot(TM) 64-Bit Server VM 23.25-b01

源代码位于。

递归无效。字符串是否分解为无数部分?如果不是,则“效率”没有差别完全可以。只是为了确保:您是否已将解析识别为应用程序的瓶颈?如果没有,您可以忽略任何替代方法可能带来的任何效率提升。一般规则是专注于可读性和可维护性;只解决性能成问题的性能问题。这是否回答了您的问题