Java 有没有更有效的方法在递归中传递对象参数?

Java 有没有更有效的方法在递归中传递对象参数?,java,recursion,Java,Recursion,我想用Java做递归,传递对象参数。大概是这样的: int recursion(Object object) { //do a little bit modification to the object int i1= recursion(modified_object_1); //do a little bit modification to the object int i2= recursion(modified_object_2); //do a

我想用Java做递归,传递对象参数。大概是这样的:

int recursion(Object object)
{
    //do a little bit modification to the object
    int i1= recursion(modified_object_1);
    //do a little bit modification to the object
    int i2= recursion(modified_object_2);
    //do a little bit modification to the object
    int i3= recursion(modified_object_3);
    return max(i1, i2, i3);
}
现在,因为对象是通过引用传递的,所以我必须克隆对象参数3次,然后将克隆的对象传递给下一个递归。然而,这可能是非常低效的,因为我做了数万次递归,而且对象的结构非常复杂。除了克隆对象之外,还有更有效的方法吗


谢谢~

我认为你无法避免复制那些对象

我建议构建一个pre函数,从这些对象中提取所需的一切,以便构建某种“尽可能小的对象”,以便在递归中复制尽可能少的字段


最好的方法是提取基本类型并将其用于递归。无论如何,要获得更具体的帮助,您应该发布更多详细信息(例如,您的对象/修改)

我认为您无法避免复制这些对象

我建议构建一个pre函数,从这些对象中提取所需的一切,以便构建某种“尽可能小的对象”,以便在递归中复制尽可能少的字段


最好的方法是提取基本类型并将其用于递归。无论如何,要获得更具体的帮助,您应该发布更多详细信息(例如,您的对象/修改)

在java中,您不能通过引用传递参数,而只能通过值传递参数。在您的例子中,一个可能的解决方法是将对象定义为
递归
方法所在的类的属性。例如:

class RecursionClass {
    private Object object;

    public void setObject(Object object) {
        this.object = object;
    }

    int recursion() {
        if(object == null)
            throw new Exception("Set the object first!");

        // define modified objects base on object


        //do a little bit modification to the object
        int i1= recursion(modified_object_1);
        //do a little bit modification to the object
        int i2= recursion(modified_object_2);
        //do a little bit modification to the object
        int i3= recursion(modified_object_3);
        return max(i1, i2, i3);
    }
}

在java中,不能通过引用传递参数,只能通过值传递参数。在您的例子中,一个可能的解决方法是将对象定义为
递归
方法所在的类的属性。例如:

class RecursionClass {
    private Object object;

    public void setObject(Object object) {
        this.object = object;
    }

    int recursion() {
        if(object == null)
            throw new Exception("Set the object first!");

        // define modified objects base on object


        //do a little bit modification to the object
        int i1= recursion(modified_object_1);
        //do a little bit modification to the object
        int i2= recursion(modified_object_2);
        //do a little bit modification to the object
        int i3= recursion(modified_object_3);
        return max(i1, i2, i3);
    }
}

首先是关于传递值和引用的一些明确性(OP在这方面似乎很清楚,但评论者似乎很困惑)。Java对象在传递给函数时不会自动克隆-对对象的引用是通过值传递的-更改函数中的对象将改变调用上下文中的对象

因此OP正确地计划,要运行他的算法,他需要首先克隆对象,然后使用克隆的副本传递递归函数链

然而,在某些情况下,还有一种可能很容易实现:

int recursion(Object object)
{
    //do a little bit modification to the object
    int i1= recursion(object);
    //undo the modification to the object
    //do a little bit modification to the object
    int i2= recursion(object);
    //undo the modification to the object
    //do a little bit modification to the object
    int i3= recursion(object);
    //undo the modification to the object
    return max(i1, i2, i3);
}
在可能的情况下(例如在搜索游戏决策树时选择可能的移动),它的工作效率更高


请注意,最后一次撤消更改是必需的,否则堆栈上较高的对象将出错。

首先,关于通过值和引用进行传递有点清楚(OP对此似乎很清楚,但评论者似乎很困惑)。Java对象在传递给函数时不会自动克隆-对对象的引用是通过值传递的-更改函数中的对象将改变调用上下文中的对象

因此OP正确地计划,要运行他的算法,他需要首先克隆对象,然后使用克隆的副本传递递归函数链

然而,在某些情况下,还有一种可能很容易实现:

int recursion(Object object)
{
    //do a little bit modification to the object
    int i1= recursion(object);
    //undo the modification to the object
    //do a little bit modification to the object
    int i2= recursion(object);
    //undo the modification to the object
    //do a little bit modification to the object
    int i3= recursion(object);
    //undo the modification to the object
    return max(i1, i2, i3);
}
在可能的情况下(例如在搜索游戏决策树时选择可能的移动),它的工作效率更高


请注意,最后一次撤消更改是必需的,否则堆栈上层的对象将出错。

请考虑使用不可变对象。当堆栈帧共享正在修改的对象时,递归算法变得特别难以考虑

Decorator模式有助于提高效率和内存使用率。例如,如果要更改一个字段:

 class UserWithAgeChanged implements User {

      private User delegate;
      private int age;

      public UserWithAgeChanged(User user, int newAge) {
          this.delegate = user;
          this.age = newAge;
      }

      @Override
      public String getName() {
          return delegate.getName();
      }

      // similar methods for all delegated fields

      @Override
      public String getAge() {
          return age;
      }
 }
(有一些图书馆可以帮助你做这类事情,比如

现在,您可以执行以下递归操作:

   // silly functionality, but you get the point
   void recurse(User user) {
        if(user.getAge() == 44) {
            return user;
        } else {
            recurse(new UserWithAgeChanged(user, user.getAge() + 1);
        }
   }

这将创建一个代理链,大多数是小对象,最后是更大的“根”
User
对象。在一个更复杂的算法中,您将得到一个由不可变对象组成的网络,但不会有太多的复制或克隆进行,而是会有大量的委托。

考虑使用不可变对象。当堆栈帧共享正在修改的对象时,递归算法变得特别难以考虑

Decorator模式有助于提高效率和内存使用率。例如,如果要更改一个字段:

 class UserWithAgeChanged implements User {

      private User delegate;
      private int age;

      public UserWithAgeChanged(User user, int newAge) {
          this.delegate = user;
          this.age = newAge;
      }

      @Override
      public String getName() {
          return delegate.getName();
      }

      // similar methods for all delegated fields

      @Override
      public String getAge() {
          return age;
      }
 }
(有一些图书馆可以帮助你做这类事情,比如

现在,您可以执行以下递归操作:

   // silly functionality, but you get the point
   void recurse(User user) {
        if(user.getAge() == 44) {
            return user;
        } else {
            recurse(new UserWithAgeChanged(user, user.getAge() + 1);
        }
   }

这将创建一个代理链,大多数是小对象,最后是更大的“根”
User
对象。在更复杂的算法中,您将得到一个由不可变对象组成的网络,但不会有太多的复制或克隆操作,而是会有大量的委托。

如果需要数万次递归,请在对象定义中设置一个递归周期。或者详细说明你想要达到的目标以及对对象的那些微小的修改,你可能会考虑删除递归方法来实现动态编程迭代方法,类似于经典的斐波那契程序,人们总是在介绍类中使用一个修正,你是通过值传递对象,通过引用传递对象(即在内存中传递对象的地址)是最有效的方法。尽管如此,在JavaJava中不可能总是按值传递参数……这似乎是一个XY问题(为什么必须使用递归?),但为了给出一个直接的答案,我想说,为什么不在递归调用后立即传递原始对象并撤销更改?如果需要数万个参数,请在对象定义中设置一个递归周期