有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java递归或循环

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

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);
    }
    
}

现在我很自豪我已经创建了一个递归方法,但我知道这可以通过循环来解决

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


共 (5) 个答案

  1. # 1 楼答案

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

  2. # 2 楼答案

    一般的递归

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

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

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


    代码维护

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


    你的代码

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

    在我看来,calculateAverage(hour + 1);应该移到函数之外,因为它对阅读代码的人来说也更清晰。每个电话都是独立的

  3. # 3 楼答案

    它取决于上下文。例如,如果我有一个Composite对象树(在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;
        }
    

    否则,如果性能很重要,请注意,由于函数/方法调用开销,递归调用在大多数情况下比简单循环慢

    所以最重要的是,如果你需要在递归是一种自然解决方案的对象中进行迭代,并且你不需要冒StackOverflowError的风险,那就使用递归吧。否则你最好还是打个圈

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

  4. # 4 楼答案

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

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

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

  5. # 5 楼答案

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

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

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