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

时间:2017-08-16 13:34:10

标签: 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 little bit modification to the object
    int i3= recursion(modified_object_3);
    return max(i1, i2, i3);
}

现在,因为对象是通过引用传递的,所以我必须克隆对象参数3次并将克隆的对象传递给下一个递归。然而,这可能是非常低效的,因为我进行数万次递归并且对象结构复杂。除了克隆对象之外,还有更有效的方法吗?

谢谢〜

4 个答案:

答案 0 :(得分:3)

首先,关于通过值和参考的一点清晰度(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);
}

在可能的情况下(例如,在搜索游戏决策树时选择可能的移动),它可以更有效地工作。

请注意,上次撤消更改是必需的,否则堆叠上方的对象将出错。

答案 1 :(得分:3)

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

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

(有些图书馆可以帮助你做这类事情 - 比如Immutables library

现在你可以做一些递归的事情,如:

   // 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对象。在一个更复杂的算法中,你最终会得到一个不可变对象的网络,但是不会有太多的复制或克隆 - 而是会有很多的委托。

答案 2 :(得分:1)

我不认为你可以避免复制这些物品

我建议建立一个预功能,从这些对象中提取你需要的一切,以便构建某种尽可能小的对象"这样在递归中你可以复制尽可能少的字段。

如果您只是提取原始类型并将其用于递归,那将是最好的。无论如何,为了获得更具体的帮助,您应该发布更多细节(例如您的对象/修改)

答案 3 :(得分:-1)

在java中,您无法通过引用传递参数,只能按值传递。在您的情况下,可能的解决方法是将对象定义为您的recursion方法所在的类的属性。例如:

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