简体   繁体   中英

Is there a more efficient way passing object parameters in recursion?

I would like to do recursion in Java, passing object parameters. Something like this:

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

Now, because objects are passed by reference, I have to clone the object parameters 3 times and pass the cloned objects to the next recursion. However, this can be extremely inefficient cause I'm doing the recursion tens of thousands of times and the object is complicatedly structured. Is there a more efficient way to do this other than cloning the object?

Thank you~

Firstly a bit of clarity regarding passing by value and reference (the OP seems clear on this but the commenters seem confused). Java objects are not automatically cloned when passed to a function - a reference to the object is passed by value - changing the object in a function will alter the object in the calling context.

So the OP correctly plans that to run his algorithm he needs to first clone the objects and then use the cloned copy to pass down the recursive function chain.

There is however one other possibility which can be easily implemented in SOME cases:

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

In cases where this is possible (for example when selecting a possible move when searching game decision trees) it works much more efficiently.

Note that the last undo the changes is required as otherwise the objects higher up the stack will go awry.

Consider using immutable objects. Recursive algorithms become especially difficult to think about when stack frames are sharing an object that's getting modified.

The Decorator pattern can help with efficiency and memory usage. For example, if you're changing one field:

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

(There are libraries to help you do this kind of thing - such as the Immutables library )

Now you can do something recursive like:

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

This will create a chain of delegates, most being tiny objects, with the bigger "root" User object at the end. In a more complex algorithm, you'll end up with a network of immutable objects, but there won't be much copying or cloning going on -- rather there will be lots of delegation.

I don't think that you can avoid to copy those objects

I suggest is to build a pre-function that extract from those objects everything you need in order to build some kind of "as small as possible objects" so that in the recursion you copy as few fields as you can.

The best would be if you could just extract primitive types and use those for your recursion. Anyway for more concrete help you should post more details (eg you objects/modifications)

In java you cannot pass parameters by reference, just by value. A possible workaround for that in your case would be defining the object as an attribute to the class where your recursion method is within. For example:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM