JAVA 递归问题,kotlin 尾递归优化

递归(Recursive)是指自己方法内部调用自己

如求 1- n(n>1)之间的和:


    public static long sum(long n) {

        if (n == 1) {
            return 1;
        }

        return n + sum(n - 1);

    }

这是使用递归的方式求和,很消耗内存,比如我求 1 - 2147483647 ( Integer.MAX_VALUE ) ,就会StackOverflowError ,堆栈溢出

StackOverflowError

但是其实使用循环是可以计算出的

    static long sum(long n){
        
        long res = 0;
        while (n > 0){
            res+=n;
            n--;
        }
        
        return res;
    }

继续求 1 - 2147483647 ( Integer.MAX_VALUE ) 的和

结果

第二行是结果,第三行是用时

那么什么是尾递归呢?

就是递归时只返回函数本身,没有其他计算
即:

    static long sum(long n,long sum){
        
        if (n == 0){
            return sum;
        }
        return sum(n - 1,n+sum);
    }

在某些语言中,写成这样的递归在编译时会被自动优化,或者运行时会清除上次的栈信息,因为上次执行中的任何数据在下次执行时都是无关的

那么在 java上既然可能会出现问题,那么在使用递归时需要注意,尽量使用循环,或者在计算很小的数据时使用

在kotlin中,我们写成尾递归的时候,配合关键字 tailrec

如下:

tailrec fun sum(n: Int, res: Long): Long {
    if (n == 0) {
        return res;
    }
    return sum(n - 1, res + n)
}

测试代码

fun main(args: Array) {

    val start = System.currentTimeMillis()
    val result = sum(Int.MAX_VALUE, 0)
    val end = System.currentTimeMillis()

    println(result)
    println("time:${end - start}")

}
kotlin结果

结果和上面使用循环的结果一致
时间上好像变短了。。。

反编译kotlin生成的class文件

JAVA 递归问题,kotlin 尾递归优化_第1张图片
kotlin生成的class

现在测试不加 tailrec 试试

StackOverflowError

一样会溢出
再次反编译class查看


JAVA 递归问题,kotlin 尾递归优化_第2张图片
kotlin class

代码并没有做优化
因此在使用 kotlin 时,可以使用关键字 tailrec 来进行优化尾递归
注意:必须是尾递归!!!

而使用 java编写时,尽量避免使用递归做深度的计算,可以使用循环代替!

你可能感兴趣的:(JAVA 递归问题,kotlin 尾递归优化)