以下来自 John Hann 的实现,这段代码引起了我的注意,它用巧妙的方法把方法调用的结果缓存起来了。
关于装饰器,书中用到的名字是 Memoizer,为啥是这个名字,也给了一个解释: 这个 Memoizer 装饰类应该长什么样呢?...首先 Memoizer 得实现 Computable 接口,然后重写其 compute 方法: public class Memoizer implements Computable<A,...所谓的“用装饰器”,不过就是这样的一行代码而已: Memoizer memoizer = new Memoizer(new ScoreQuery()); 用 Memoizer 这个通用类,来装饰了 ScoreQuery...所以,Memoizer 类里面还得搞一个缓存也就是 map,并且把它给用起来, public class Memoizer implements Computable {...memoizer = new Memoizer(new NucleicAcidTest()); 是不是扩展性一下就体现出来了。
使用函数的方式 在下面的代码片段中,我们创建了一个高阶的函数 memoizer。有了这个函数,将能够轻松地将缓存应用到任何函数。...从 memoizer 函数中,我们返回一个新函数,根据上面讨论的闭包原则,这个函数无论在哪里执行都可以访问 cache。...要将 memoizer 函数应用于最初递归的 fibonacci 函数,我们调用 memoizer 函数,将 fibonacci 函数作为参数传递进去。...const fibonacciMemoFunction = memoizer(fibonacciRecursive) 测试 memoizer 函数 当我们将 memoizer 函数与上面的例子进行比较时...,结果如下: memoizer 函数以 42,982,762 ops/sec 的速度提供了最快的解决方案,比之前考虑的解决方案速度要快 100%。
functools def memoize(fn): print('start memoize') known = dict() @functools.wraps(fn) def memoizer...(): print('%s : %s'%(k, known[k]), end = ' ') print() # return known[args] return memoizer...) : 36 (9,) : 45 (10,) : 55 通过取消注释的对比,可以得到如下结论: 装饰器memoize实际上对于函数nsum()只执行了第一次加载的时候的预处理,然后就是nsum = memoizer...在上例子中,通过known[args] = fn(*args)先执行fn函数,即上例子中nsum(10),然后就进入递归,t同时调用memoizer()和nsum()函数10次,且先memoizer再nsum
4 import java.util.Map; 5 6 /** 7 * Created by yulinfeng on 12/25/16. 8 */ 9 public class Memoizer1...final Map cache = new HashMap(); 11 private final Computable c; 12 13 public Memoizer1...> cache = new ConcurrentHashMap(); 11 private final Computable c; 12 13 public Memoizer2...= new ConcurrentHashMap>(); 12 private final Computable c; 13 14 public Memoizer3...= new ConcurrentHashMap>(); 10 private final Computable c; 11 12 public Memoizer
private final Map cache = new HashMap(); private final Computable c; public Memoizer1...* @param * @param */ class Memoizer2 implements Computable{ private final Map... cache = new ConcurrentHashMap(); private final Computable c; Memoizer2(Computable...final Map> cache = new ConcurrentHashMap(); private final Computable c; Memoizer3...} } /** * 使用ConcurrentHashMap的putIfAbsent解决原子问题 * 若计算取消则移除 * @param * @param */ class Memoizer
但又不能影响对象内容的情况下 三、应用案例 import functools def memoize(fn): known = dict() @functools.wraps(fn) def memoizer...if args not in known: known[args] = fn(*args) return known[args] return memoizer
以下是同步方法的实现方式: public class Memoizer1 implements Computable { @GuardedBy("this") private...final Map cache = new HashMap(); private final Computable c; public Memoizer1(Computable...} return result; }} 由于同步方法是对整个容器上锁,所以并发的效率不好,因此要使用并发容器作为计算结果的缓存,改进代码如下: public class Memoizer2...final Map cache = new ConcurrentHashMap(); private final Computable c; public Memoizer2...完善的代码如下: public class Memoizer implements Computable { // 记录那些结果的计算已经开始 private final
例如: Supplier cachedValue = Memoizer.memoize(() -> expensiveDatabaseCall()); 上述代码中,Memoizer.memoize
var memoizer=function(memo,fundamental){ var shell=function(n){ var result=memo[n];...memo[n]=result; } return result; }; return shell; }; var fibonacci=memoizer
return result; }; return fib; })(); fibonacci(10) //55 抽象的递归记忆函数 var memoizer...memo[n] = result; } return result; } return shell; }; var fibonacci = memoizer
不着急,下一小节说,我先把后半句话给解释了: 这个漏洞的发生概率要远小于 Memoizer2 中发生的概率。...Memoizer2 就是指前面用 ConcurrentHashMap 替换 HashMap 后的方案。 那么为什么引入 Future 之后的这个方案,触发刚刚说到的 bug 的概率比之前的方案小呢?
不过现在已经有一个解决方案Memoizer 其实很简单,就是用一个key来记录这次的Future,然后放在一个Map里,下次用到时再从Map里取出来。
classes/jdk/internal/jrtfs/SystemImage.class classes/jdk/internal/loader/AbstractClassLoaderValue$Memoizer...$RecursiveInvocationException.class classes/jdk/internal/loader/AbstractClassLoaderValue$Memoizer.class
领取专属 10元无门槛券
手把手带您无忧上云