当前位置: 首页 > 知识库问答 >
问题:

泛型memoize函数引发ConcurrentModificationException

关项明
2023-03-14
public static <T, U> Function<T, U> memoize(Function<Function<T, U>, Function<T, U>> f) {
    return new Function<T, U>() {

        final Map<T, U> cache = new HashMap<>();
        final Function<T, U> body = f.apply(this);

        @Override
        public U apply(T t) {
            return cache.computeIfAbsent(t, body);
        }
    };
}
Function<BigInteger, BigInteger> fibonacci =
    memoize(self -> n -> n.equals(ZERO) ? ZERO
        : n.equals(ONE) ? ONE
        : self.apply(n.subtract(ONE)).add(self.apply(n.subtract(TWO))));

for (long i = 0; i < 1000; ++i)
    System.out.println(fibonacci.apply(BigInteger.valueOf(i)));
Function<Integer, Function<Integer, Function<Integer, Integer>>> tarai =
    memoize(fx -> x ->
        memoize(fy -> y ->
            memoize(fz -> z -> x <= y ? y
                : fx.apply(fx.apply(x - 1).apply(y).apply(z))
                    .apply(fx.apply(y - 1).apply(z).apply(x))
                    .apply(fx.apply(z - 1).apply(x).apply(y)))));

System.out.println(tarai.apply(12).apply(6).apply(0));

我使用的是Java14,但我记得它在过去的版本中是有效的。

共有1个答案

吴高峰
2023-03-14

computeif缺席的Javadoc表示:

如果在计算过程中检测到映射函数修改了此映射,则该方法将在尽最大努力的基础上抛出 ;ConcurrentModificationException ;

大概是因为它在内部迭代映射。

if (map.containsKey(t)) {
  return map.get(t);
}
U value = body.apply(t);
map.put(t, value);
return value;
 类似资料:
  • 同样的规则也可以适用于函数:在使用前给出 <T> 后,类型 T 就变成了泛型。 使用泛型函数有时需要显式地指明类型参量。这种可能的情况包括,调用返回类型是泛型的函数,或者编译器没有足够的信息来推导类型参量。 函数调用使用显式指定的类型参量,如下所示: fun::<A, B, ...>(). struct A; // 具体类型 `A`。 struct S(A); //

  • 泛型函数定义 泛型函数可以用于任何类型. 这里是上面提到的swapTwoInts(_:, _:)函数的泛型版本, 叫做swapTwoValues(_:_:) func swapTwoValues<T>(_ a: inout T, _ b: inout T) { let temporaryA = a a = b b = temporaryA } 上面的s

  • 我正在尝试制作一些适用于数字的通用函数,但我正在努力处理函数签名。 也许我是从错误的角度来讨论这个问题,但到目前为止,我是在这里独立完成的。我并不是一心要这样做;因此,如果我从错误的角度来解决这个问题(创建一个通常有用的数学函数库),那么一定要教育我。 假设我想要一个函数,将两个数字相加: 这不会编译。这里是一个游乐场:https://play.integer32.com/?version=sta

  • 问题内容: 我正在学习中,文档和交互式课程说,空可以容纳任何类型,因为它不需要其他实现的方法。 举个例子: …将打印出来… 因此,我想我的问题是这是实现通用函数的方法,还是还有另一种更合适的方法来实现它们。 问题答案: Go范式通常是通过在非空接口中实现行为来避免这种情况。例如,假设您要打印特定于类型的格式的内容: 或者,您可以为知道如何进行字符串自身设置的接口定义一个接口(该接口在库中以形式存在

  • 我不想为每个类型T编写这个方法只是为了调用getMessage()并将其传递给下一个方法。 有可能写出这样的方法吗?我只想访问ConstraintViolation接口的方法,这些方法不依赖于类型T(如字符串getMessage())。

  • 返回 memoized(缓存的)函数。 使用 Object.create(null) 创建一个没有 Object.prototype 的空对象(这样如果输入值类似 'hasOwnProperty',那么这些属性就不会被解析)。 通过首先检查该特定输入值的函数输出是否已经被缓存,如果没有,则返回一个函数,该函数将作为单个参数提供给 memoized 函数。 const memoize = fn =>