我想在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次并将克隆的对象传递给下一个递归。然而,这可能是非常低效的,因为我进行数万次递归并且对象结构复杂。除了克隆对象之外,还有更有效的方法吗?
谢谢〜
答案 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);
}
}