JGSK - Groovy - 02.Memorized

Table Of Contents

Memoized

Memoized 即缓存功能。Groovy 可以对方法和闭包的结果进行缓存,从而再下次传入同样的参数时直接返回缓存的结果。对于那些耗时很久的计算过程来说这一点可以节约不少时间。

对闭包结果进行缓存

调用 memoize() 方法就可以对闭包结果进行缓存

def closure1 = { Integer x ->
    println "Closure argument $x"
    x
}.memoize()

调用闭包

closure1(3)
closure1(3)
closure1(3)
closure1(4)
closure1(4)
closure1(4)

控制台只有两个输出语句,证明闭包结果被成功缓存了起来。

Closure argument 3
Closure argument 4

对方法的执行结果进行缓存

对方法的执行结果进行缓存需要使用注解 @Memoized

为了区分使用缓存和不使用缓存的区别,本次使用斐波那契数列进行测试。斐波那契数列指的是这样一个数列 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89,即从第 3 项开始每项的值都是其前两项之和。

斐波那契数列的 Groovy 实现

int fibonacci(int n) {
    println("fibonacci for $n")
    if (n == 0 || n == 1) return n
    return fibonacci(n - 1) + fibonacci(n - 2)
}

由于其中使用了递归所以该方法在使用时会被大量调用

fibonacci(5)

输出结果

fibonacci for 5
fibonacci for 4
fibonacci for 3
fibonacci for 2
fibonacci for 1
fibonacci for 0
fibonacci for 1
fibonacci for 2
fibonacci for 1
fibonacci for 0
fibonacci for 3
fibonacci for 2
fibonacci for 1
fibonacci for 0
fibonacci for 1

换成使用缓存的实现

@Memoized
static def memoFibonacci(int n) {
    println("memoFibonacci for $n")
    if (n == 0 || n == 1) return n
    return memoFibonacci(n - 1) + memoFibonacci(n - 2)
}

调用方法

memoFibonacci(5)

输出结果

memoFibonacci for 5
memoFibonacci for 4
memoFibonacci for 3
memoFibonacci for 2
memoFibonacci for 1
memoFibonacci for 0

可以看到重复调用次数比起不使用缓存少了很多,并且接着调用 memoFibonacci(4) 之类的都会直接返回结果,因为从 5 以下的结果都已经被缓存了。

Groovy 还可以通过以下方法控制缓存的数量

@Memoized(maxCacheSize = 3)