我有一个递归算法,它逐个字符地遍历字符串,并对其进行解析以创建树状结构。我希望能够跟踪解析器当前所在的字符索引(对于错误消息以及其他任何内容),但我并不热衷于实现像元组这样的东西来处理多个返回的类型。
我尝试使用 Integer 类型,在方法外部声明并传递给递归方法,但因为它是最终的,递归调用增量在我返回时被“遗忘”。(因为Integer值的递增使得传值对象引用指向一个新对象)
有没有办法获得类似于不会污染我的代码的工作?
我有一个递归算法,它逐个字符地遍历字符串,并对其进行解析以创建树状结构。我希望能够跟踪解析器当前所在的字符索引(对于错误消息以及其他任何内容),但我并不热衷于实现像元组这样的东西来处理多个返回的类型。
我尝试使用 Integer 类型,在方法外部声明并传递给递归方法,但因为它是最终的,递归调用增量在我返回时被“遗忘”。(因为Integer值的递增使得传值对象引用指向一个新对象)
有没有办法获得类似于不会污染我的代码的工作?
这是一种 hack,但有时我使用可变的 AtomicInteger 来做这样的事情。我还看到传入大小为 1 的 int[] 的情况。
我正在使用的当前解决方案是:
int[] counter = {0};
然后将其传递给递归算法:
public List<Thing> doIt (String aString, int[] counter) { ... }
当我想增加它时:
counter[0]++;
不是超级优雅,但它确实有效......
整数是不可变的,这意味着当您将它作为参数传递时,它会创建一个副本而不是对同一项目的引用。(解释)。
要获得您正在寻找的行为,您可以编写自己的类,它就像 Integer only mutable。然后,只需将它传递给递归函数,它会在递归中递增,并且当您在递归结束后再次访问它时,它仍将保持其新值。
编辑:请注意,使用 int[] 数组是此方法的一种变体……在 Java 中,数组也是通过引用传递的,而不是像原语或不可变类那样复制。
既然您已经发现了伪可变整数“hack”,那么这个选项怎么样:
创建一个单独的 Parser 类对您有意义吗?如果这样做,您可以将当前状态存储在成员变量中。您可能需要考虑如何处理任何线程安全问题,对于这个特定的应用程序来说这可能是多余的,但它可能对您有用。
您可以只使用一个静态 int 类变量,每次调用 doIt 方法时该变量都会递增。
你也可以这样做:
private int recurse (int i) {
if (someConditionkeepOnGoing) {
i = recurse(i+1);
}
return i;
}
老实说,我会重新编码该函数以使其成为使用循环的线性算法。这样,如果您单步执行一个非常大的字符串,您就没有机会耗尽堆空间。此外,您不需要额外的参数来跟踪计数。
这也可能会使算法更快,因为它不需要对每个字符进行函数调用。
当然,除非有特定原因,它需要递归。
我能想到的一种可能性是将计数存储在类的成员变量中。这当然假设公共doIt
方法仅由单个线程调用。
另一种选择是重构公共方法以调用私有辅助方法。私有方法将列表作为参数并返回计数。例如:
public List<Thing> doIt(String aString) {
List<Thing> list = new ArrayList<Thing>();
int count = doItHelper(aString, list, 0);
// ...
return list;
}
private int doItHelper(String aString, List<Thing> list, int count) {
// ...
// do something that updates count
count = doItHelper(aString, list, count);
// ...
return count;
}
这假设您可以在公共doIt
方法中进行错误处理,因为count
变量实际上并没有传递回调用者。如果你需要这样做,你当然可以抛出一个异常:
public List<Thing> doIt(String aString) throws SomeCustomException {
List<Thing> list = new ArrayList<Thing>();
int count = doItHelper(aString, list, 0);
// ...
if (someErrorOccurred) {
throw new SomeCustomException("Error occurred at chracter index " + count, count);
}
return list;
}
如果不了解您的算法的实际工作原理,很难知道这是否会有所帮助。