精华内容
下载资源
问答
  • 2021-02-13 00:31:35

    最近总有人问我,Java SE8里有没有针对尾调用做优化(这是一种特殊的函数调用)。这个优化和递归调用密切相关,而递归调用对函数式语言来说尤其重要,因为它们通常都基于递归来进行设计编码。本文会介绍到什么是尾调用,怎样可以对它进行有效的优化,以及Java 8在这方面是如何做的。

    在深入这个话题之前,我们先来了解下什么是尾调用。

    什么是尾调用?

    尾调用指的是一个方法或者函数的调用在另一个方法或者函数的最后一条指令中进行(为了简单,后面我就都称作函数调用了)。Andrew Koenig在他的博客中有关于这个话题的介绍。下面定义了一个foo()函数作为例子:

    int foo(int a) {

    a = a + 1;

    return func(a);

    }

    func()函数的调用是foo()函数的最后一条语句,因此这是一个尾调用。如果在调用了func()之后,foo()函数还执行了别的指令才返回的话,那么func()就不再是一次尾调用了。

    你可能在想这些语义有什么意义。如果尾调用不是一个递归的函数调用的话,这些概念确实不重要。比如:

    int fact(int i, int acc) {

    if ( i == 0 )

    return acc;

    else

    return fact( i – 1, acc * i);

    }

    int factorial(int n) {

    if ( n == 0 )

    return 1;

    else

    return fact( n – 1, 1 );

    }

    尾调用的优化

    任何的尾调用,不只是尾递归,函数调用本身都可以被优化掉,变得跟goto操作一样。这就意味着,在函数调用前先把栈给设置好,调用完成后再恢复栈的这个操作(分别是prolog和epilog)可以被优化掉。比如说下面的这段代码:

    int func_a(int data) {

    data = do_this(data);

    return do_that(data);

    }

    函数do_that()是一个尾调用。没有优化过的汇编代码看起来大概是这样的:

    ... ! executing inside func_a()

    push EIP ! push current instruction pointer on stack

    push data ! push variable 'data' on the stack

    jmp do_this ! call do_this() by jumping to its address

    ... ! executing inside do_this()

    push EIP ! push current instruction pointer on stack

    push data ! push variable 'data' on the stack

    jmp do_that ! call do_that() by jumping to its address

    ... ! executing inside do_that()

    pop data ! prepare to return value of 'data'

    pop EIP ! return to do_this()

    pop data ! prepare to return value of 'data'

    pop EIP ! return to func_a()

    pop data ! prepare to return value of 'data'

    pop EIP ! return to func_a() caller

    ...

    注意到对于数据以及EIP寄存器(用来返回数据并且恢复指令指针),POP指令被连续执行了多次。可以通过一个简单的JMP指令将一组关联的epilog和prolog操作(将数据和EIP进行压栈)优化掉。这是因为dothat()函数会替funca函数执行这段epilog代码。

    这个优化是安全的,因为funca函数在dothat()返回后就不再执行别的指令了。(注意:如果要对dothat()返回的值进行处理的话,就不能执行这个优化,因为dothat()就不再是一个尾调用了)。

    优化前的代码

    优化后的代码

    int func_a(int data) {

    data = do_this(data);

    push EIP ! prolog

    push data ! prolog

    jmp do_this ! call

    ...

    pop data ! epilog

    pop EIP ! epilog

    push EIP ! prolog

    push data ! prolog

    jmp do_this ! call

    ...

    pop data ! epilog

    pop EIP ! epilog

    return do_that(data);

    push EIP ! prolog

    push data ! prolog

    jmp do_that! call

    ...

    pop data ! epilog

    pop EIP ! epilog

    jmp do_that ! goto ...

    }

    pop data ! epilog

    pop EIP ! epilog

    pop data ! epilog

    pop EIP ! epilog

    比较一下第三行,你就可以看到节省了多少行机器代码。当然光这个而言并不能代表这个优化的真正价值。如果和递归结合到一起的话,这个优化的价值就显现出来了。

    如果你再看下上面的那个递归的阶乘函数,你会发现如果使用了这个优化的话,所有原来不断重复的prolog和epilog汇编代码现在都消失了。最终把下面的递归伪代码:

    call factorial(3)

    call fact(3,1)

    call fact(2,3)

    call fact(1 6)

    call fact(0,6)

    return 6

    return 6

    return 6

    return 6

    return 6

    变成这个迭代式的伪代码:

    call factorial(3)

    call fact(3,1)

    update variables with (2,3)

    update variables with (1,6)

    update variables with (0,6)

    return 6

    return 6

    也就是说,它用一个循环替换掉了递归,大多数C/C++,Java程序员也正是这么干的。这个优化不止是减少了大量的递归函数调用带来的prolog和epilog,它还极大的减轻了栈的压力。不作这个优化的话,计算一个很大的数的阶乘很可能会让栈溢出——也就是,用光了所有分配给栈的内存。把代码优化成循环后就消除了这个问题。由于函数式语言的开发人员经常使用递归,所以大多数函数式语言的解释器都会进行尾调用的优化。

    Java是怎么做的?

    正如我前面提到的,Java程序员一般都使用循环,而尽量不用递归。比如,下面是一个迭代式的阶乘的实现:

    int factorial(int n) {

    int result = 1;

    for (int t=n; t > 1; t--)

    result *= t;

    return result;

    }

    因此对大多数Java开发人员来说,Java不进行尾调用优化并不是什么大问题。不过我猜或许很多Java程序员都没有听说过尾调用优化这回事。不过当你在JVM上运行函数式语言的话,这就成为一个问题了。递归的代码在自己语言的解释器里运行得好好的,可能一到JVM上就突然把栈给用完了。

    值得注意的是,这并不是JVM的BUG。这个优化对经常使用递归的函数式语言的开发人员来说非常有用。我最近经常和Oracle的Brian Goetz提到这个优化,他总是说这个在JVM的开发计划表上,不过这不是一个优先级特别高的事。就目前来说,你最好自己去做优化,当你使用函数式语言在JVM上进行开发的时候,尽管避免使用过深的递归调用。

    文章来自于:https://blog.csdn.net/azhegps/article/details/72638906

    更多相关内容
  • java递归查询

    千次阅读 2021-12-06 21:23:16
    递归建立数据库的字段要建立pid 既pid是父id 这里的pid要能在id找到 找到就说明当前id的组织是父组织 如果找不到就说明的顶级id 图中的主菜单1就是顶级组织 public Menu getMenuTree() { //先查询顶级目录 ...

    递归建立数据库的字段要建立pid
    既pid是父id
    在这里插入图片描述
    这里的pid要能在id找到 找到就说明当前id的组织是父组织 如果找不到就说明的顶级id 图中的主菜单1就是顶级组织

      public Menu getMenuTree() {
            //先查询顶级目录
            LambdaQueryWrapper<Menu> menuLambdaQueryWrapper = new LambdaQueryWrapper<>();
            menuLambdaQueryWrapper.eq(Menu::getPid, "0");
            Menu menusBase = menuMapper.selectOne(menuLambdaQueryWrapper);
            //查询除了顶级组织以外的组织
            LambdaQueryWrapper<Menu> menuLambdaQueryWrapper2 = new LambdaQueryWrapper<>();
            menuLambdaQueryWrapper2.ne(Menu::getPid, "0");
            List<Menu> menuLNotBase = menuMapper.selectList(menuLambdaQueryWrapper2);
            List<Menu> menus = iterateMenus(menuLNotBase, menusBase.getId());
            menusBase.setMenuChildren(menus);
            return menusBase;
        }
    

    反复调用iterateMenus方法 直到循环遍历结束

        /**
         * 多级组织查询方法
         *
         * @param menuVoList 不包含最高层次组织的组织集合
         * @param pid        父类id
         * @return
         */
        public List<Menu> iterateMenus(List<Menu> menuVoList, String pid) {
            List<Menu> result = new ArrayList<>();
            int a =0;
            for (Menu menu : menuVoList) {
                //获取菜单的id
                String menuid = menu.getId();
                //获取菜单的父id
                String parentid = menu.getPid();
    
                    if (parentid.equals(pid)) {
                        //递归查询当前子菜单的子菜单
                        List<Menu> iterateMenu = iterateMenus(menuVoList, menuid);
                        menu.setMenuChildren(iterateMenu);
                        result.add(menu);
                    }
            }
            return result;
        }
    
    

    Entity有些字段不需要 我加是因为自己的业务

    @Data
    @NoArgsConstructor
    @TableName("Menu")
    public class Menu {
    
        private String  id;
        private String name;
        private String pid;
        @TableField(exist = false)
        private List<Menu> menuChildren;
        @TableField(exist = false)
        private Boolean nextRank;
    }
    
    展开全文
  • 优化递归的效率zz

    2021-04-23 07:07:27
    函数递归调用是很常见的做法,但是它往往是低效的,本文探讨优化递归效率的思路。1、尾递归转换成迭代尾递归是一种简单的递归,它可以用迭代来代替 比如 求阶乘函数的递归表达 int f( int n) {if(n<=0)return 1;...

    函数递归调用是很常见的做法,但是它往往是低效的,本文探讨优化递归效率的思路。

    1、尾递归转换成迭代

    尾递归是一种简单的递归,它可以用迭代来代替 比如 求阶乘函数的递归表达

    7fb4027ec5830a04616fbcae9e46d5b8.png int f( int n)

    7ea44f1a15e4cb23e75f01d619e3d62c.png {

    a1d082ba3978b59bc6ac33e532442564.pngif(n<=0)return 1;

    cbec3f219a68959eb766dc8ae9dd4c3e.pngreturn n*f(n-1);

    0f3fc47a567ff5658f1af4cd0a37f4e3.png}

    可以转换成完全等价的循环迭代

    cf064e98ff250ea1c361a1f36541165b.png int f( int n)

    74790f408668fbbcc4d808454df7b5e7.png {

    a8e190e9f01990036918a470866d956b.pngint r=0;

    9731e2a9eb71c209bf5e957fa6e101a2.pngwhile(n-->0)

    a8aa0ab6b147a9cffdce22aebe185025.png r*=n;

    ec1cc69c3d1f1eddcde6de29cb6ab48f.pngreturn r;

    da0701cf8c236af3f63d7280a41d1979.png}

    尾递归是最简单的情形,好的编译器甚至可以自动的识别尾递归并把它转换成循环迭代。

    2、动态规划

    我一直把动态规划看作尾递归的推广(个人观点),在2维或更高的情况下,直接使用递归会造成大量的重复计算,例如在斐波那契数列的递归关系 Fib(n+2)=Fib(n+1)+Fib(n)中 Fib(3)在计算Fib(4)和Fib(5)都会用到 他被重复计算了2遍,当数列长度增大时 这种浪费会变得越来越明显。

    动态规划方法将可能需要的结果全部计算出来 并保存 一般来说 动态规划从最小数开始 自底向上计算所有值(因为后面的结果会用到前面的结果) 直到得到的结果中包含了要求的结果。

    9b384dcad4ad52313e5fe5919d9b1e21.png int Fib(unsigned n)

    a4a87a41f7981689ff58712ec767654a.png {

    e013fd93079f409b2d99b73c37c6e9a7.pngif(n==1)return 1;

    bed7a472ff033b699d35a3b440391298.pngif(n==0)return 0;

    ed6a1c2fdd1762daa80b5498cd67f7d7.pngreturn Fib(n-1)+Fib(n-2);

    98a5d77b79416c83a8bdaaa06cd173a4.png}

    c96ec131e5cabcf6088be7b244b309ce.png

    12c726e8defdb152014e87de0f72c136.png

    0447de2dba7e34a6c885865af44f008d.png int Fib(unsigned n)

    e06c5722d05bd9e4074fab720720a461.png {

    8fd2f48cb398c408595c0fe226fd7c5b.pngint* f=new int[n+1];

    1ac11a8e066f4ec7a6e0afc521f1d6cf.png f[1]=1;f[0]=0;

    5c7d7e19b267ff5a1d8636684b973ae6.pngfor(int i=0;i<=n;i++);

    90ee89ee6427eaba4337513be684d35a.png f[i]=f[i-1]+f[i-2];

    277545c0e5388200ba3af2da16c1d4a5.pngint r=f[n];

    46c81c0ec84a556aa8c76f022e68fc75.png delete[] f;

    dee7a63441455db60bb81fa9f0bb140f.pngreturn r;

    1eaf702e6569262786e04d38ea808ed4.png}

    动态规划不会造成重复运算 但是 它可能计算不需要的结果 例如关系式

    a(n)=a(n-2)+a(n-4);

    使用动态规划会计算很多不需要的结果,尽管如此,它的效率远远高于直接递归运算。

    实际上,大部分时候动态规划把指数级时间复杂度的递归运算变成了多项式级时间复杂度的递推。

    3、备忘录

    减少重复值的另一个方法是使用备忘录,每次成功计算一个结果 ,就将它存入备忘录中,当再次遇到此问题时,无需重复计算,直接取出即可。

    备忘录方法和直接递归相似,只是在函数在计算之前先访问备忘录,如果在备忘录中找到,就无须再计算,直接返回。

    备忘录结构可以使用关联数组 哈希表等实现,特别地,当递归参数是整数时 直接用数组就可以了。

    与动态规划相比,备忘录消耗了额外的备忘录查找时间,并且和直接递归一样 有大量的多余函数调用开销,但它不会造成额外计算。

    4、内联

    这是来自Efficient C++的方法,C++编译器不会把递归函数内联,这样,函数调用的开销变得很大。为了提高效率,必须手动内联函数。

    递归函数无法完全内联,但是我们可以把它展开,这是前面Fibnacci函数的一层展开

    133d97c1a4231d1a24ee9db7ac825a7a.png int Fib(unsigned n)

    c41aae076f7aac626f8eaea0f2a1ec97.png {

    9d8425dbd50d87c2a13482bc41153137.pngif(n==1)return 1;

    e38f4c9a742549786571d0390fb9410f.pngif(n==0)return 0;

    b165581086ef5a7c31b93cf4450667fd.png

    2af27644d65beac0140a9937e504b3b2.pngint fn1,fn2;

    8b3edfbda9a003fee1fdf3a908e49694.pngif(n-1==1)fn1=1;

    f39199d9d65e2118bd5e46b9a7cf4533.pngelse if(n-1==0)fn1=0;

    15b977b4c64ba224a52341063e5a274f.pngelse fn1=Fib(n-2)+Fib(n-3);

    7ae4728e23efceb8136229be41162d58.png

    df12378d91885249ea7af79a642c4380.pngif(n-2==1)fn2=1;

    6345b552cf6c2a70a7c57b230f0a47c6.pngelse if(n-2==0)fn2=0;

    0fd373c051680b04dbd425791d0e9156.pngelse fn2=Fib(n-3)+Fib(n-4);

    55ba851211a4d64f82765c8d960acf58.png

    b00ba8933017ec0cbe46a2c271717d82.pngreturn fn1+fn2

    7604deea761a7ee9ba7cb74aefa2a590.png}

    5、解递归

    尽管我们倾向于虐待计算机 让它帮我们处理较复杂的问题,但是很多时候我们需要获得效率,就必须自己动手,其实很多递归式可以手动解出,组合数学为我们提供了不少工具:

    (1)解齐次递归方程

    简单的递归方程可以按以下步骤求解:

    解Fibonacci函数的递归方程

    36_47.png

    首先把它转换成下面的式子

    36_48.png

    这个代数方程被称为递归方程的特征方程,下一步是解特征方程求出它的所有解,对这个例子来说

    36_49.png

    根据组合数学的结论

    36_50.png

    再由

    F(0)=0和F(1)=1可以得出方程组

    36_51.png

    解这个方程组可得到a和b的值

    36_52.png

    代入前面的公式可以求出Fibnacci通项公式

    36_53.png

    验证后可以知道,这个公式是正确的,显然用此公式做浮点运算,比使用递归方式快得多。

    (2)母函数

    组合数学中还提供了一种更强有力的处理手段:生成函数(又称为母函数)

    仍然以求解Fibonacci数列为例,为了易于理解,我这里把生成函数描述成一个以Fibonacci数列为系数的多项式。即

    36_54.png

    现在考虑这样一个多项式

    36_55.png

    按g(x)的定义,可以这样展开

    36_56.png

    36_57.png

    36_58.png

    这个时候不要忘记我们的递推公式,可以进一步化简为

    36_59.png

    这个式子与g(x)非常像,将它两边同时乘以x

    36_60.png

    36_61.png

    36_62.png

    再整理一下等式

    36_63.png

    利用F(0)=0,F(1)=1可以求出

    36_64.png

    这样 我们求出了g(x),等等,g(x)是什么来着?不是以Fibonacci数列为系数的多项式么?现在求出的东西是什么?不要急,用泰勒级数展开就能得到通项公式了,结果跟上面的是一样的。(太麻烦了,略过略过^_^)

    https://www.cnblogs.com/end/category/82543.html

    展开全文
  • } //递归实现查询多级类目 public ExamCategory fillMenuNode(ExamCategory examCategory) { ExamCategory examCategorySearch = new ExamCategory(); examCategorySearch.setParentId( examCategory.getCategoryId...

    类目表是多级目录表,数据如下:

    想获取所有数据的多级目录,代码如下:

      /**
         * 获取树形接口的 类目
         *
         * @return
         */
        @Override
        public List<ExamCategory> selectExamCategoryTreeList() {
            //1、 获取所有的一级目录
            ExamCategory examCategory = new ExamCategory();
            examCategory.setParentId( 0 );
            List<ExamCategory> examCategoryList = examCategoryDao.selectExamCategoryList( examCategory );
            
            List<ExamCategory> parentList = new ArrayList<>();
            for (ExamCategory category : examCategoryList) {
                if (category.getParentId().intValue() == 0) {
                    parentList.add( category );
                }
            }
    
            //获取一级目录下的多级目录
            if (parentList != null) {
                for (ExamCategory category : parentList) {
                    fillMenuNode( category );
                }
            }
    
            return parentList;
        }
    
    
        //递归实现查询多级类目
        public ExamCategory fillMenuNode(ExamCategory examCategory) {
            ExamCategory examCategorySearch = new ExamCategory();
            examCategorySearch.setParentId( examCategory.getCategoryId() );
            List<ExamCategory> examCategoryList = examCategoryDao.selectExamCategoryList( examCategorySearch );
            if (CollectionUtils.isEmpty( examCategoryList )) {
                return examCategory;
            }
            List<ExamCategory> subMenuList = examCategoryList.stream().map( subMenu -> fillMenuNode( subMenu ) ).collect( Collectors.toList() );//递归实现查询多级菜单
            examCategory.setChildrenList( subMenuList );
            return examCategory;
        }

    展开全文
  • Java用队列优化递归

    千次阅读 2017-05-11 03:52:52
    遍历的树深的时候,使用队列来优化递归
  • 主要介绍了Java8使用lambda实现Java的尾递归的相关资料,需要的朋友可以参考下
  • Java 递归查询组织机构树

    千次阅读 2020-11-15 15:01:16
    需求:现有一个A集合(机构id集合),需要利用A集合查询出集合中所有机构的子级机构,层级(不知道一共有多少级),最终返回所有的子级机构(就是返回一个childOrganList,不包括A集合) 文章目录代码实现聊聊递归...
  • java实现多级递归查询

    千次阅读 2021-04-21 19:37:25
    一、java实现多级递归查询 1、实体类对象(省略了一些字段) @Data @EqualsAndHashCode(callSuper = true) @Accessors(chain = true) @TableName("SYS_USER") public class User { private static final long ...
  • 递归优化小记

    2021-02-13 00:31:35
    前言一般地,对于java语言而言,普通的递归调用是在java虚拟机栈上完成的.假如a()是一个递归方法,那么在其内部再调用自己的时候,假设为a1(),那么a1()方法变量表将创建在a()方法栈帧之上,从而形成了一个新的栈帧.因此...
  • 由于递归的效率和性能问题,请各路大神给出更优化的方式。package com.lwc.test;import org.junit.Test;import java.util.ArrayList;import java.util.Arrays;import java.util.List;/*** @au...
  • 什么又是尾递归优化?码农唐磊 程序猿石头今天,咱们来聊聊递归函数。为啥忽然想到递归?其实就从电影名字《恐怖游轮》《盗梦空间》想到了。图片java递归是啥?递归函数你们确定写过,学校上课的时候,估计最开始的...
  • 省市县的递归查询

    2022-04-11 10:04:22
    项目做地址查询,用递归一次将省市县以子集的形式全查出来。
  • 递归优化

    2021-03-18 10:40:13
    1.什么是递归?程序调用自身的编程技巧称为递归( recursion...下面看一个例子:public class JavaTest {public static int method(int num) {if (num > 1)return num + method(num - 1);elsereturn num;}public s...
  • 图解Java递归

    2021-09-11 17:26:42
    目录一、一个经典的递归例子二、尾递归优化三、图解递归 一、一个经典的递归例子 (注:本文例子只用于探讨,不考虑n<=0 等复杂情况。) int factorial(int n){ if(n==1){ return 1; }else{ return n*...
  • Java递归函数讲解

    2021-03-15 12:53:55
    Java中的递归什么是递归?函数直接或间接调用自身的过程称为递归,相应的函数称为递归函数。使用递归算法,某些问题可以很容易地解决。这类问题的例子有Hanoi的Towers(TOH)、序/前序/后序树遍历、图的DFS等。递归中...
  • 本文简单介绍以递归方式处理树形数据。 package com.agileai.esb.smc.domain; import java.util.*; import net.sf.json.JSONArray; public class TreeBuilder { List<TreeBuilder.Node&g
  • java树形结构查询优化

    千次阅读 2020-12-22 21:09:45
    java树形结构查询优化 public class TreeTest { // 定义全局变量,统计地柜中总的循环次数 private static int time; /** * 初始化数据,模拟从数据查询出来的数据 * @return */ public static List<Menu...
  • java实现省市县多级联动 实体类## 标题 @Data @AllArgsConstructor @NoArgsConstructor public class Dict { private static final long serialVersionUID = 1L; private Long id; private Long parentId; ...
  • 递归遍历某个路径下的所有文件,找到以某个指定或某类文件,输出其路径,以遍历F盘查找java文件(.java结尾)为例,进行讨论 2.普通实现         最简单的实现就是直接使用...
  • 最近在做的需求有一个点是,查询上下级关系,本想着用oracl的树查询,但是会莫名少很一些数据(因为此查询涉及循环,但是这种循环是被业务允许的),也没空具体研究oracle的树查询,后来用java递归的方式,递归查询...
  • 为什么需要优化递归这里不用说了吧!先看下面的示例: 相关代码: /** * 使用递归实现计算斐波那契数列 */ console.log("使用递归实现计算斐波那契数列"); console.time('start') let count = 0;//用于统计总的...
  • Java递归

    2021-05-19 01:27:47
    经过适当处理,尾递归形式的函数的运行效率可以被极大地优化。尾调用原则上都可以通过简化函数调用栈的结构而获得性能优化(称为“尾调用消除”),但是优化尾调用是否方便可行取决于运行环境对此类优化的支持程度...
  • Java版爬楼梯递归版最佳优化

    千次阅读 2017-05-21 10:36:22
    爬楼梯Java 爬楼梯
  • 原标题:java8使用lambda实现Java的尾递归前言本篇介绍的不是什么新知识,而是对前面讲解的一些知识的综合运用。众所周知,递归是解决复杂...而Java的编译器并没有这样的优化,本篇就要完成这样一个对于尾递归优化...
  • 1.所谓的递归慢到底是什么原因呢? 大家都知道递归的实现是通过调用函数本身,函数调用的时候,每次调用时 要做地址保存,参数传递等,这是通过一个递归工作栈实现的。具体是每次 调用函数本身要保存的内容包括:...
  • 一、递归,伪递归,迭代实现n! package com.njbdqn.test02; /** * 递归,伪递归,迭代实现n! */ public class RecursionTest { public static void main(String[] args) { System.out.println(recurse(5)); //...
  • 优化java递归实现笛卡尔积算法

    千次阅读 2019-09-19 09:58:36
    不多说了,直接撸代码,总共实现不到10行(这一套是博主自己想的,写之前没看那个已经被抄的不能再多的代码,看上去有点像,没办法递归只能这样): public static void main(String[] args) { List...
  • 本文使用了三种方式实现了斐波那契数列——数组、递归优化递归。 此文重点是对斐波那契数列的实现方式效率的比较及优化。 一、数组实现斐波那契数列 测试代码: public class ArrayTest { public static void ...
  • Java支持尾递归调用,但是AFAIK并没有优化它们。我认为这是Scala编译器,只是这样做,而不是JVM本身。查看Scala中的@tailrec注释,看看编译器能够做些什么呢:)但是无论Java / JVM是否优化尾部递归,您的功能将比需要...
  • Java基础:循环与递归

    2022-01-21 22:06:01
    方法递归1.不使用递归,计算1~n的和2.使用递归,计算1~n的和 1.不使用递归,计算1~n的和 //不使用递归,计算1~n的和 public class NoRecursion{ public static void main(String[] args){ //1~5的和 System.out...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 74,571
精华内容 29,828
关键字:

java递归查询优化

java 订阅