1. 程式人生 > >Groovy中那些神奇註解之Memoized

Groovy中那些神奇註解之Memoized

PS:強烈推薦Groovyr官方文件,相當的詳細,地址:http://www.groovy-lang.org/documentation.html,不用擔心是英文,有點程式碼經驗的,一看示例程式碼就知道是什麼意思了。

好了,閒話少說,第一個註解:Memoized

Memoized的全稱是:groovy.transform.Memoized,在groovy.transform包下,有很多相關的註解,可以好好了解一下

至於Memoized的作用,看名字就很明白了,就是“記住”,沒錯,就是把方法的執行結果快取起來,下次呼叫時,如果引數一樣,那方法就不再計算而是直接返回結果了,該註解對於那些引數範圍比較少,並且只要引數一定,那麼結果肯定也是唯一的方法,有著很好的加速效果。

舉個最簡單,但是個人覺得最能體現Memoized效果的例子,大家應該都實現過用遞迴方式實現斐波那契(fibnacci)數列吧,但是純粹的不加優化的遞迴方式是相當相當的沒效率的,在我的電腦上,計算到40左右,電腦就有點跑不動了,看看程式碼:

class Fibnacci{
    long total = 0 //用來統計一共計算了多少次
    int n //計算多少的數列

    public Fibnacci(int n){
        this.n = n
    }

    def fibnacci_1(n){
        total ++
        n < 2
? 1 : fibnacci_1(n-1) + fibnacci_1(n-2) } @groovy.transform.Memoized def fibnacci_2(n){ total ++ n < 2 ? 1 : fibnacci_2(n-1) + fibnacci_2(n-2) } //測試不使用Memoized def runWithoutMem(){ long start = System.currentTimeMillis() total = 0 def
val = fibnacci_1(n) long time = System.currentTimeMillis() - start println "未使用Memoized,${n}的Fibnacci值是${val},共用時${time}毫秒,函式呼叫共${total}次" } //測試使用Memoized def runWithMem(){ long start = System.currentTimeMillis() total = 0 def val = fibnacci_2(n) long time = System.currentTimeMillis() - start println "使用Memoized,${n}的Fibnacci值是${val},共用時${time}毫秒,函式呼叫共${total}次" } } def fib = new Fibnacci(40) fib.runWithoutMem() fib.runWithMem()

fibnacci_1和fibnacci_2方法實現是完全一樣的,唯一的不一致就是一個加上了註解,同時我在類裡面加上了一個變數total,來統計方法一共被呼叫了多少次,把上面的程式碼複製到Groovy自帶的GroovyConsole程式中(神器呀),直接就可以執行,看看結果:

Result: 未使用Memoized,40的Fibnacci值是165580141,共用時6040毫秒,函式呼叫共331160281次
使用Memoized,40的Fibnacci值是165580141,共用時4毫秒,函式呼叫共41

結果很驚人吧,因為Memoized把計算的結果快取下來了,如果引數一樣就不用再重複計算了,所以效率自然大大提高,這就好像我們用陣列方法來實現fibnacci從而提高效率原理是差不多的,不過這樣小小的一個註解,可以少寫好多程式碼省不少事了:)

親測 有效