Java 递归还是循环

Java 递归还是循环,java,loops,recursion,Java,Loops,Recursion,我有一个计算一些统计数据的方法: public void calculateAverage(int hour){ if (hour != 20) { int data =0; int times = 0; for (CallQueue cq : queues) { data += cq.getCallsByTime().get(hour); times++; }

我有一个计算一些统计数据的方法:

public void calculateAverage(int hour){

    if (hour != 20) {
        int data =0; 
        int times = 0;
        for (CallQueue cq : queues) {
            data += cq.getCallsByTime().get(hour);
            times++;
        }       
        averageData.add((double)data/times);
        calculateAverage(hour + 1);
    }
    
}
现在我非常自豪我已经创建了一个递归方法,但我知道这可以用循环来解决

我的问题是:解决这类问题最好是递归还是使用循环?

通常是递归 一般来说,递归的代价更高,因为每次函数递归时都必须使用变量副本修改堆栈

需要保存一组地址和状态,以便递归过程可以在特定运行后返回到正确的状态

如果可能的话,迭代会更好。递归,当迭代不能切割它时,或者将导致更复杂的代码


代码维护 从维护的角度来看,调试迭代代码比递归过程容易得多,因为与考虑特定递归相比,理解任何特定迭代的状态相对容易


你的代码 过程调用自身,但每次运行与上一次运行的结果无关每次运行都是独立的,这通常是最大的损失,那里的递归可能没有必要


在我看来,
calculateAverage(小时+1)
应该移到函数之外,因为阅读代码的人也会更清楚。每个调用都是独立的。

对于这个特定问题,运行时没有太大差异。我个人更愿意使用迭代,我认为它会更简单,更容易理解,但我认为每个人都有自己的想法

现在一些递归函数(比如递归斐波那契数)应该通过迭代来实现,因为它们可以有指数增长


一般来说,我不使用递归,除非它能让我的问题更容易理解

你应该调查周边环境。对于大型递归,堆栈可能会溢出,对于循环,这是+1

我不确定哪一个运行得更快,但考虑到JIT和其他因素,这相对容易衡量


代码维护方面:对于我们大多数人来说,理解和修复循环比递归容易得多。开发人员的时间通常比微小的性能差异更重要。

它取决于上下文。例如,如果我有一个由
复合
对象(在SWT中)组成的树,并且您希望遍历它们,那么最简单的方法就是像这样使用递归:

    private boolean checkControlParent(Composite comp) {
        boolean ret = false;
        if (comp != null) {
            if (this.equals(comp)) {
                ret = true;
            } else {
                ret = checkControlParent(comp.getParent());
            }
        }
        return ret;
    }
否则,如果性能很重要,请注意,由于函数/方法调用开销,递归调用在大多数情况下比简单循环慢

因此,主要的问题是,如果您需要遍历递归是一种自然解决方案的对象,并且您不需要冒险使用
StackOverflowerError
继续使用递归。否则,您可能最好使用循环


还有一件事:递归方法有时更难阅读、理解和调试。

在Java、C和Python中,递归与迭代(通常)相比是相当昂贵的,因为它需要分配新的堆栈框架。在一些C编译器中,可以使用编译器标志来消除这种开销,这种开销将某些类型的递归(实际上是某些类型的尾部调用)转换为跳转而不是函数调用。()

递归被认为是迭代的更“优雅”的解决方案。这里的
hour
的有效值是什么?当您使用hour>20调用
calculateAverage
时会发生什么?例如21?这甚至不是递归函数,它只是一个递归过程。它不使用递归来达到任何实际效果。是的,在Java中,递归从来不是首选,因为它不是一种尾部调用优化语言,所以您不必要地强调调用堆栈。这是否回答了您的问题@当实际问题通过递归更好地解决时,它们比递归复杂得多。当然,这里不是这样,所以迭代看起来更清晰。例如,使用递归比迭代更容易写入和读取基数为2的FFT。