【问题标题】:The Java stack and recursionJava 栈和递归
【发布时间】:2019-08-04 15:01:06
【问题描述】:

我的问题是关于 Java 堆栈的设计。是在设计时考虑到了递归,还是由于堆栈的结构,递归成为了一个东西?

【问题讨论】:

  • 递归是几乎所有比 FORTRAN 更新的计算机语言的基本设计原则。
  • 调用堆栈是更多语言的常用实现技术,包括 Fortran。
  • 实际上你需要 3 个堆栈来模拟(即使只有几乎)各种递归(河内塔)。但问题是:“模仿”恰到好处。为什么要模拟并让编译器从递归方法中创建非递归的东西?虽然有理由(至于任何事情)Java 强调(或强调)这一点。所以你可以递归,但java不会将给定的递归代码复杂地重构为非递归的东西。

标签: java recursion design-patterns stack history


【解决方案1】:

一个明显的不回答:

实际上,具有递归的“真实事物”是tail recursion,编译器认识到这一点,并在掩护下将其优化为迭代循环。

令人惊讶的是:Java 无法做到这一点。因此,在现实世界中,递归和 Java 不能很好地结合在一起。仅仅几千次递归调用可能会使您的 JVM 崩溃。所以你绝对尽量避免在真正的java中递归。对于小的孤立问题,这是一件好事。但除此之外,递归在 Java 中“不是”一件事。

而堆栈的设计可能更多基于 20 年前为虚拟机创建一个简单、易于移植的系统的想法。而且这两个概念(堆栈和递归)都早在 Java v1 发布之前就已经存在了。

【讨论】:

    【解决方案2】:

    Java8 添加了 lambda 表达式和函数式接口,如下所述:https://blog.knoldus.com/tail-recursion-in-java-8/

    这允许我们定义自己的尾递归接口:

    @FunctionalInterface
    public interface TailCall {
        TailCall apply();
        default boolean isComplete() {
            return false;
        }
        default T result() {
            throw new Error("not implemented");
        }
        default T invoke() {
            return Stream.iterate(this, TailCall::apply)
                    .filter(TailCall::isComplete)
                    .findFirst()
                    .get()
                    .result();
        }
    }
    

    因此你可以这样做:

    public class Factorial{
        public static TailCall factorialTailRec(final int factorial, final int number) {
            if (number == 1)
                return TailCalls.done(factorial);
            else
                return call(() -> factorialTailRec(factorial * number, number - 1));
        }
    }
    

    然而,Java 本身并没有考虑到任何尾递归优化。与 Scala(我认为更好的 Java)相比,Scala 具有 @tailrec 注释,因此当提供此提示并假设该函数是真正的 tailrec 函数时,编译器会将递归优化为非递归方式。

    @tailrec
    def gcd(a: Int, b: Int): Int = …
    

    请在此链接中查看更多详细信息:https://www.scala-exercises.org/scala_tutorial/tail_recursion

    【讨论】:

    • Java 8 没有添加任何尾递归接口或对 TCO 的特定支持,并且您链接的博客没有另外说明。但是,随着 Java 8 中 lambda 的引入,程序员可以通过尾调用优化来模拟递归。这种模拟是一种编程技术,而不是一种语言特性。
    • @JohnBollinger 你是对的,我会修改答案。
    • 绝对是一个不错的答案:-)
    猜你喜欢
    • 2015-12-08
    • 2015-04-04
    • 2023-03-27
    • 2018-03-26
    • 2021-12-15
    • 2016-11-09
    • 1970-01-01
    • 1970-01-01
    • 2015-12-17
    相关资源
    最近更新 更多