4

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

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

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

4

8 回答 8

2

这是一种 hack,但有时我使用可变的 AtomicInteger 来做这样的事情。我还看到传入大小为 1 的 int[] 的情况。

于 2008-08-29T16:40:44.903 回答
2

我正在使用的当前解决方案是:

int[] counter = {0};

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

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

当我想增加它时:

counter[0]++;

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

于 2008-08-29T16:44:06.267 回答
2

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

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

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

于 2008-08-29T16:47:59.440 回答
2

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

创建一个单独的 Parser 类对您有意义吗?如果这样做,您可以将当前状态存储在成员变量中。您可能需要考虑如何处理任何线程安全问题,对于这个特定的应用程序来说这可能是多余的,但它可能对您有用。

于 2008-08-29T16:52:37.917 回答
1

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

于 2008-08-29T18:05:34.933 回答
1

你也可以这样做:

private int recurse (int i) {

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

    return i;
}
于 2012-03-06T16:47:23.727 回答
0

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

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

当然,除非有特定原因,它需要递归。

于 2008-08-29T16:59:16.073 回答
0

我能想到的一种可能性是将计数存储在类的成员变量中。这当然假设公共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;
}

如果不了解您的算法的实际工作原理,很难知道这是否会有所帮助。

于 2008-08-29T17:51:32.767 回答