如何在Java中使用递归算法来保持“完成的事情”?

时间:2008-08-29 16:38:10

标签: java recursion coding-style integer final

我有一个递归算法,逐个字符地逐步执行字符串,并解析它以创建树状结构。我希望能够跟踪解析器当前所处的字符索引(对于错误消息和其他任何内容),但我并不热衷于实现类似于元组的处理多个返回类型的东西。

我尝试使用在方法外部声明并传递到递归方法的Integer类型,但因为它是最终的,所以当我返回时,递归调用增量被“遗忘”。 (因为Integer值的增量使得值传递值的对象引用点在新对象上)

有没有办法得到类似的工作,不会污染我的代码?

8 个答案:

答案 0 :(得分:2)

这是一种黑客行为,但有时我会使用一个可变的AtomicInteger来做这样的事情。我也看到了传入大小为1的int []的情况。

答案 1 :(得分:2)

我目前使用的解决方案是:

int[] counter = {0};

然后将其传递给递归算法:

public List<Thing> doIt (String aString, int[] counter) { ... }

当我想增加它时:

counter[0]++;

不是超级优雅,但它有效...

答案 2 :(得分:2)

整数是不可变的,这意味着当您将其作为参数传递时,它会创建副本而不是对同一项的引用。 (explanation)。

要获得您正在寻找的行为,您可以编写自己的类,就像Integer一样只是可变的。然后,只是将它传递给递归函数,它在递归中递增,当递归结束后再次访问它时,它仍将保持其新值。

编辑:请注意,使用int []数组是此方法的变体...在Java中,数组也通过引用传递,而不是像原语或不可变类一样复制。

答案 3 :(得分:2)

既然你已经发现了伪可变整数“hack”,那么这个选项怎么样:

您是否有必要制作单独的Parser课程?如果执行此操作,则可以将当前状态存储在成员变量中。您可能需要考虑如何处理任何线程安全问题,并且对于此特定应用程序可能有点过分,但它可能对您有用。

答案 4 :(得分:1)

你可以使用一个静态int类变量,每次调用doIt方法时它都会递增。

答案 5 :(得分:1)

你也可以这样做:

private int recurse (int i) {

    if (someConditionkeepOnGoing) {
        i = recurse(i+1);
    }

    return i;
}

答案 6 :(得分:0)

老实说,我会重新编写函数,使其成为一个使用循环的线性算法。这样,如果您单步执行非常大的字符串,则无法用尽堆空间。此外,您不需要额外的参数来跟踪计数。

这也可能会使算法更快,因为它不需要为每个字符进行函数调用。

除非有特定原因,否则需要递归。

答案 7 :(得分:0)

我能想到的一种可能性是将计数存储在类的成员变量中。这当然假设公共doIt方法仅由单个线程调用。

另一个选择是重构public方法来调用私有帮助器方法。 private方法将列表作为参数并返回计数。例如:

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

如果不了解更多关于算法实际工作情况的信息,很难知道这是否会有所帮助。