gpt4 book ai didi

Java 通用 lambda 记忆化

转载 作者:行者123 更新时间:2023-12-01 14:10:22 26 4
gpt4 key购买 nike

我想用 Java 编写一个用于通用内存的实用程序,我希望代码能够如下所示:

Util.memoize(() -> longCalculation(1));

在哪里

private Integer longCalculation(Integer x) {
try {
Thread.sleep(1000);
} catch (InterruptedException ignored) {}
return x * 2;
}

为此,我想我可以做这样的事情:

public class Util{
private static final Map<Object, Object> cache = new ConcurrentHashMap<>();
public interface Operator<T> {
T op();
}

public static<T> T memoize(Operator<T> o) {
ConcurrentHashMap<Object, T> memo = cache.containsKey(o.getClass()) ? (ConcurrentHashMap<Object, T>) cache.get(o.getClass()) : new ConcurrentHashMap<>();
if (memo.containsKey(o)) {
return memo.get(o);
} else {
T val = o.op();
memo.put(o, val);
return val;
}
}
}

我原以为这会起作用,但我没有看到任何内存。我已经追踪到 o.getClass() 每次调用都不同。我在想我可以尝试获取 T 的运行时类型,但我想不出这样做的方法。

最佳答案

answer by Lino指出了代码中的几个缺陷,但如果不重用相同的 lambda 则不起作用。

这是因为 o.getClass() 返回的不是 lambda 返回的类,而是 lambda 本身的类。因此,下面的代码返回两个不同的类:

Util.memoize(() -> longCalculation(1));
Util.memoize(() -> longCalculation(1));

我不认为有一个好的方法可以在不实际执行可能长时间运行的代码的情况下找出返回类型的类,这当然是您想要避免的。

考虑到这一点,我建议将类作为第二个参数传递给 memoize()。这会给你:

@SuppressWarnings("unchecked")
public static <T> T memoize(Operator<T> o, Class<T> clazz) {
return (T) cache.computeIfAbsent(clazz, k -> o.op());
}

这是基于您将 cache 的类型更改为:

private static final Map<Class<?>, Object> cache = new ConcurrentHashMap<>();

不幸的是,您必须将 Object 向下转换为 T,但您可以通过 @SuppressWarnings("unchecked")< 保证它是安全的 注释。毕竟,您可以控制代码并且知道值的类将与映射中的键相同。

另一种方法是使用 Guavas ClassToInstanceMap :

private static final ClassToInstanceMap<Object> cache = MutableClassToInstanceMap.create(new ConcurrentHashMap<>());

然而,这不允许您在不强制转换的情况下使用 computeIfAbsent(),因为它返回一个 Object,因此代码会变得有点冗长:

public static <T> T memoize(Operator<T> o, Class<T> clazz) {
T cachedCalculation = cache.getInstance(clazz);
if (cachedCalculation != null) {
return cachedCalculation;
}
T calculation = o.op();
cache.put(clazz, calculation);
return calculation;
}

作为最后的旁注,您不需要指定自己的功能接口(interface),但您可以使用 Supplier 接口(interface):

@SuppressWarnings("unchecked")
public static <T> T memoize(Supplier<T> o, Class<T> clazz) {
return (T) cache.computeIfAbsent(clazz, k -> o.get());
}

关于Java 通用 lambda 记忆化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61652033/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com