我使用以下两种方法获得以下示例class
:
Process.java:
public class Process {
public Process() {
}
public static void countRecursive(int num) {
System.out.println("countRecursive: " + num++);
if (num <= 10) countRecursive(num);
else return;
}
public static void countWhile(int num) {
do System.out.println("countWhile: " + num++);
while (num <= 10);
}
}
主要课程:
public static void main(String[] args) {
Process.countRecursive(0);
Process.countWhile(0);
}
输出:
countRecursive: 0
countRecursive: 1
countRecursive: 2
countRecursive: 3
countRecursive: 4
countRecursive: 5
countRecursive: 6
countRecursive: 7
countRecursive: 8
countRecursive: 9
countRecursive: 10
countWhile: 0
countWhile: 1
countWhile: 2
countWhile: 3
countWhile: 4
countWhile: 5
countWhile: 6
countWhile: 7
countWhile: 8
countWhile: 9
countWhile: 10
但我想知道建议使用哪种“技术”以及原因。
提前致谢。
答案 0 :(得分:35)
由于方法调用开销和调用堆栈的使用,递归会变慢。
Java也没有执行尾调用优化,所以不要指望它。 (虽然JVM上有一些语言可以进行尾调用优化,包括Clojure和Kotlin)
另一个缺点可能是,如果你填满堆栈,可能会有StackOverflowError
的风险。
如果您这样做只是为了尝试,我建议使用可以在java JDK中找到的VisualVM。它是一个分析器,可用于对这种情况进行基准测试。
请注意 我不建议使用递归只是为了花哨。如果你真的需要它(例如遍历树),请使用它。
答案 1 :(得分:12)
您应该使用时间测量来运行代码。这里有100个递归/ 100循环的输出:
Recursive time: 90941
While time: 5180
这清楚地表明while循环比递归更快。
您可以通过运行以下代码来检查我的测量值:
public class Process {
public Process() {
}
public static void countRecursive(int num) {
num++;
if (num <= 100) countRecursive(num);
else return;
}
public static void countWhile(int num) {
do
num++;
while (num <= 100);
}
public static void main(String[] args) {
Long start = System.nanoTime();
Process.countRecursive(0);
System.out.println("Recursive time: " + (System.nanoTime() - start));
Long startWhile = System.nanoTime();
Process.countWhile(0);
System.out.println("While time: " + (System.nanoTime() - startWhile));
}
}
答案 2 :(得分:10)
我不建议使用Recursion,因为每个递归都存储在堆栈中。因此,您需要为每个递归调用存储方法参数,局部变量等,以便在调用之前维护方法的状态。
另外,显然你不应该使用这种问题进行递归。它应该留给某些特定的任务,只有当你真的无法避免使用它们时。
此外,您还可以对代码进行基准测试,以查看哪个代码运行得更快。你会有一个想法。
答案 3 :(得分:7)
递归调用将堆栈帧添加到调用堆栈。循环没有。循环通常比递归更快,除非递归是像分而治之的算法的一部分(你的例子不是)。
你应该能够计算每个方法的执行时间,并找出一个方法比另一个方法快多少。
答案 4 :(得分:6)
一般来说,我赞成迭代(例如一段时间或for循环)而不是递归,因为:
答案 5 :(得分:6)
通常,如果可能,递归被优化为循环,这意味着由于各种原因,包括堆栈帧分配和堆栈帧溢出,如果两个解在其他方面相等,则迭代优于递归。见Tail Recursion
因此,忽略Java不优化Tail Recursion的事实,循环应该更快。
另请查看this
答案 6 :(得分:5)
在java中,与while循环相比,递归的成本很低,因为它需要分配新的堆栈帧。在替代方法是显式管理堆栈
的情况下,递归可能会更快答案 7 :(得分:3)
其他人都说的是真的。我想补充一点:对于你发布的问题,计数1到10,使用递归或迭代都可以,因为它们都需要花费的时间可以忽略不计。一般来说,在现代计算机系统上,你不需要过多担心一个过程需要多长时间才能完成(除非你处理大型数据集),因为内存非常便宜且CPU非常强大。
通常,你编写一个程序,但是你首先感觉最舒服,使用良好的编程实践。如果在此之后运行需要很长时间,那么就优化它。
不是在研究这个级别的迭代和递归比较是不是一件坏事。同样,迭代通常比递归更可取。我的观点是要吸取的教训是,虽然有很多方法可以使代码快速运行,但在处理小型数据集时,通常不需要担心它们。)