Каковы различные методы для memoization в Java? [закрыто]

19

Я знаю об этом Ссылка , но есть ли что-нибудь еще?     

задан ranv01 02.09.2010 в 06:08
источник
  • В этом примере выполняется memoization для всех методов объекта через прокси. Но типичная memoization - одна из функций в то время. Эта прокси-техника будет раздражать, когда вы не хотите замечать все методы объекта. –  lacroix1547 02.09.2010 в 07:45

3 ответа

12

Запоминание также легко с простой простой Java-формой.

Вы можете сделать это с нуля со следующими классами повторного использования.

Я использую их как кеши, чей срок службы является запросом на webapp.

Конечно, используйте Guava MapMaker , если вам нужна стратегия выселения или другие функции, такие как синхронизация.

Если вам нужно memoize метод со многими параметрами, просто поместите параметры в список с помощью обоих методов и передайте этот список как единственный параметр.

abstract public class Memoize0<V> {
    //the memory
    private V value;
    public V get() {
        if (value == null) {
            value = calc();
        }
        return value;
    }
    /**
     * will implement the calculation that 
     * is to be remembered thanks to this class
     */
    public abstract V calc();
}

abstract public class Memoize1<P, V> {
    //The memory, it maps one calculation parameter to one calculation result
    private Map<P, V> values = new HashMap<P, V>();

    public V get(P p) {
        if (!values.containsKey(p)) {
            values.put(p, calc(p));
        }
        return values.get(p);
    }

    /**
     * Will implement the calculations that are
     * to be remembered thanks to this class
     * (one calculation per distinct parameter)
     */
    public abstract V calc(P p);
 }

И это используется как

    Memoize0<String> configProvider = new Memoize0<String>() {
        @Override
        public String calc() {
            return fetchConfigFromVerySlowDatabase();
        }
    };
    final String config = configProvider.get();

    Memoize1<Long, String> usernameProvider = new Memoize1<Long, String>() {
        @Override
        public String calc(Long id) {
            return fetchUsernameFromVerySlowDatabase(id);
        }
    };
    final String username = usernameProvider.get(123L);
    
ответ дан lacroix1547 02.09.2010 в 07:36
источник
  • Гува еще не утверждена для нашей среды, финансового программного обеспечения ... –  ranv01 08.09.2010 в 03:08
  • Гува еще не утверждена для нашей среды. Банковское программное обеспечение ... Но это будет сделано. Однако я ограничу размер карты, чтобы избежать утечек памяти. Я не забочусь о выселениях, так как это будет сохранено только при вызове одного метода. –  ranv01 08.09.2010 в 04:31
  • Мне нравится, как высоко проверенный код не одобрен, но что-то вставленное на SO: :) –  Robert Grant 19.05.2014 в 08:39
  • Будьте осторожны с использованием примера Memoize0, поскольку он не является потокобезопасным. Многоточие потоков может вызвать метод calc () много раз в состоянии гонки. Реализация Guava является потокобезопасной, без блокировки при инициализации get (), поскольку она использует блокировку с двойной проверкой: github.com/google/guava/blob/master/guava/src/com/google/common/... –  Daniel Marcotte 21.08.2015 в 17:22
  • Похоже, что MapMaker не существует (больше). Вместо этого попробуйте CacheBuilder. –  jpaugh 25.07.2016 в 23:16
18

Для memoize функций без параметров используйте Guava Suppliers.memoize(Supplier) . Для функций с параметрами используйте CacheBuilder.build(CacheLoader) с объектами значения параметра в качестве ключей.

    
ответ дан thSoft 03.06.2013 в 11:39
источник
  • См. также github.com/google/guava/wiki/CachesExplained –  Vadzim 26.06.2017 в 12:26
  • Пример напоминания: stackoverflow.com/questions/3636244/... –  Vadzim 26.06.2017 в 12:38
14

Да. Используйте кеши из гуавы .

Пример:

import java.math.BigInteger;

import com.google.common.base.Preconditions;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;

public class Fibonacci {
    private static final LoadingCache<Integer, BigInteger> CACHE
            = CacheBuilder.newBuilder().build(CacheLoader.from(Fibonacci::fib));

    public static BigInteger fib(int n) {
        Preconditions.checkArgument(n >= 0);
        switch (n) {
        case 0:
            return BigInteger.ZERO;
        case 1:
            return BigInteger.ONE;
        default:
            return CACHE.getUnchecked(n - 1).add(CACHE.getUnchecked(n - 2));
        }
    }
}
    
ответ дан Chris Jester-Young 02.09.2010 в 06:17
источник
  • MapMaker теперь устарел в пользу CacheBuilder: code.google.com/p/guava-libraries/wiki/MapMakerMigration –  dzieciou 08.11.2013 в 20:55
  • @dzieciou Я, наконец, обновил код до того, что работает с последней версией Guava (18.0 в текущий момент написания). И на этот раз он протестирован! –  Chris Jester-Young 22.03.2015 в 06:35