ConcurrentHashMap 抛出递归更新异常

ConcurrentHashMap throws recursive update exception

这是我的 Java 代码:

static Map<BigInteger, Integer> cache = new ConcurrentHashMap<>();

static Integer minFinder(BigInteger num) {
        if (num.equals(BigInteger.ONE)) {
            return 0;
        }
        if (num.mod(BigInteger.valueOf(2)).equals(BigInteger.ZERO)) {
            //focus on stuff thats happening inside this block, since with given inputs it won't reach last return
            return 1 + cache.computeIfAbsent(num.divide(BigInteger.valueOf(2)),
                    n -> minFinder(n));
        }
        return 1 + Math.min(cache.computeIfAbsent(num.subtract(BigInteger.ONE), n -> minFinder(n)),
                cache.computeIfAbsent(num.add(BigInteger.ONE), n -> minFinder(n)));
    }

我试图记住一个函数,该函数 returns 最少数量的操作,例如除以 2、减一或加一。 我面临的问题是当我用较小的输入调用它时,例如:

minFinder(new BigInteger("32"))

有效,但具有更大的值,例如:

minFinder(new BigInteger("64"))

它抛出递归更新异常。 有什么方法可以增加递归大小以防止出现此异常或有任何其他方法可以解决此问题吗?

来自the API docs of Map.computeIfAbsent()

The mapping function should not modify this map during computation.

The API docs of ConcurrentHashMap.computeIfAbsent() 让它更强:

The mapping function must not modify this map during computation.

(强调)

您使用 minFinder() 方法作为映射函数违反了这一规定。它似乎对某些输入有效是无关紧要的。你需要找到一种不同的方式来实现你所追求的目标。

Is there any way to increase recursion size to prevent this exception or any other way to solve this?

您可以避免 computeIfAbsent() 并以 old-school 方式做同样的事情:

BigInteger halfNum = num.divide(BigInteger.valueOf(2));
BigInteger cachedValue = cache.get(halfNum);

if (cachedValue == null) {
    cachedValue = minFinder(halfNum);
    cache.put(halfNum, cachedValue);
}
return 1 + cachedValue;

但是如果计算循环,那是不够的。您也许可以通过在递归之前将标记值放入映射中来检测到这一点,这样您就可以识别循环。