18

我的代码中有一些函数,使用 memoization 很有意义(似乎甚至是强制性的)。

我不想分别为每个功能手动实现。有什么方法(例如在 Python 中)我可以只使用注释或做其他事情,所以我可以在我想要的那些函数上自动获得它?

4

5 回答 5

15

Spring 3.1 现在提供了一个@Cacheableannotation,它正是这样做的。

顾名思义,@Cacheable 用于划分可缓存的方法 - 即,将结果存储到缓存中的方法,因此在后续调用(使用相同的参数)时,无需返回缓存中的值实际执行该方法。

于 2012-03-18T01:53:44.110 回答
7

我遇到了一个名为Tek271的记忆库,它似乎使用注释来记忆你所描述的功能。

于 2010-10-14T16:05:29.770 回答
6

我不认为有记忆化的语言本机实现。

但是你可以很容易地实现它,作为你方法的装饰器。你必须维护一个地图:你的地图的关键是参数,值是结果。

这是一个简单的实现,用于单参数方法:

Map<Integer, Integer> memoizator = new HashMap<Integer, Integer>();

public Integer memoizedMethod(Integer param) {

    if (!memoizator.containsKey(param)) {
        memoizator.put(param, method(param));
    } 

    return memoizator.get(param);
}
于 2010-10-14T15:30:50.617 回答
4

您可以使用Google番石榴库中的Function接口轻松实现您的目标:

import java.util.HashMap;
import java.util.Map;

import com.google.common.base.Function;

public class MemoizerTest {
  /**
   * Memoizer takes a function as input, and returns a memoized version of the same function.
   * 
   * @param <F>
   *          the input type of the function
   * @param <T>
   *          the output type of the function
   * @param inputFunction
   *          the input function to be memoized
   * @return the new memoized function
   */
  public static <F, T> Function<F, T> memoize(final Function<F, T> inputFunction) {
    return new Function<F, T>() {
      // Holds previous results
      Map<F, T> memoization = new HashMap<F, T>();

      @Override
      public T apply(final F input) {
        // Check for previous results
        if (!memoization.containsKey(input)) {
          // None exists, so compute and store a new one
          memoization.put(input, inputFunction.apply(input));
        }

        // At this point a result is guaranteed in the memoization
        return memoization.get(input);
      }
    };
  }

  public static void main(final String[] args) {
    // Define a function (i.e. inplement apply)
    final Function<Integer, Integer> add2 = new Function<Integer, Integer>() {
      @Override
      public Integer apply(final Integer input) {
        System.out.println("Adding 2 to: " + input);
        return input + 2;
      }
    };

    // Memoize the function
    final Function<Integer, Integer> memoizedAdd2 = MemoizerTest.memoize(add2);

    // Exercise the memoized function
    System.out.println(memoizedAdd2.apply(1));
    System.out.println(memoizedAdd2.apply(2));
    System.out.println(memoizedAdd2.apply(3));
    System.out.println(memoizedAdd2.apply(2));
    System.out.println(memoizedAdd2.apply(4));
    System.out.println(memoizedAdd2.apply(1));
  }
}

应该打印:

将 2 添加到: 1

3

将 2 添加到:2

4

将 2 添加到: 3

5

4

将 2 添加到:4

6

3

您可以看到第二次 memoizedAdd2 被调用(应用)到参数 2 和 1,apply 中的计算实际上并没有运行,它只是获取存储的结果。

于 2010-10-14T17:24:14.677 回答
1

Cyclops为函数、供应商、可调用对象、谓词和扩展方法提供记忆(通过方法引用)(参见 javadoc

例如

给定一个变量来计算我们的方法被实际调用的次数,我们可以看到被记忆的函数实际上只执行了一次方法。

int called = 0;

cached = Memoise.memoiseQuadFunction(this::addAll);

assertThat(cached.apply(1,2,3,4),equalTo(10));
assertThat(cached.apply(1,2,3,4),equalTo(10));
assertThat(called,equalTo(1));

private int addAll(int a,int b,int c, int d){
    called++;
    return a+b+c+d;
}
于 2015-06-11T17:12:25.747 回答