Поиск записи в интервале в Guava Cache

Я оцениваю некоторые результаты с помощью Spring SpEL и хочу кэшировать эти результаты, чтобы мне не приходилось оценивать выражения с одинаковыми параметрами.

Кешированный ключевой объект:

@Data
@AllArgsConstructor
public class CachedResult {
    private String baseName;
    private Interval interval;

    public boolean isBetweenInclusive(final DateTime date) {
        return interval.contains(date) || interval.getEnd().isEqual(date);
    }
}

Мое решение найти запись с interval что охватывает данное dateTime:

public String getEvaluatedResult(final String baseName, final DateTime dateTime) {
    return cache.asMap().entrySet()
            .stream()
            .filter(entry -> entry.getKey().getBaseName().equals(baseName) && entry.getKey().isBetweenInclusive(dateTime))
            .findFirst()
            .map(Map.Entry::getValue)
            .orElse(null);
}

Я хотел использовать cache.get(key, valueLoader) метод, так что он может поместить значения в сам кеш при необходимости, но я не могу придумать, как использовать isBetweenInclusive и этот метод.

Моя попытка с комментарием, где я попал в проблемы:

public class MyCache {

    private final Cache<CachedResult, String> cache;

    public DefaultRolloverCache(final int expiration) {
        this.cache = CacheBuilder.newBuilder()
                .expireAfterWrite(expiration, TimeUnit.MINUTES)
                .build();
    }

    public String getFileName(final String baseName, final DateTime dateTime, final Callable<String> valueLoader) {
        try {
            return cache.get(new CachedResult(baseName, null/*How to find an interval that covers the given dateTime?*/), valueLoader);
        } catch (final ExecutionException e) {
            throw new IllegalArgumentException(String.format("Cannot read fileName from cache with basename: '%s' and dateTime: %s", baseName, dateTime), e);
        }
    }
}

Я называю этот метод как:

cache.getFileName(baseName, new DateTime(), () -> doSlowCalculations(baseName));

Конечно, так как я не знаю, как использовать упомянутый метод, я должен использовать cache.put(new CachedResult(...)) ставить записи в кеш сам.

Есть ли лучший способ отфильтровать кэш, чем вызов asMap и фильтровать его как карту? Могу ли я как-то использовать cache.get(key, valueLoader) или даже гуавы CacheLoader чтобы он мог вводить значения автоматически?

По мере увеличения производительности у меня будет максимум 5-10 записей одновременно, но я буду много читать из них, поэтому время чтения очень важно для меня, и я не уверен, что моя текущая реализация, которая повторяется 5-10 записей все время и проверка каждого из них - лучший подход.

1 ответ

Решение

Мое окончательное решение после прочтения комментария Луи написал:

public String getFileName(final String baseName, final DateTime dateTime, final Supplier<String> valueLoader) {
    final Optional<String> cached = cache.asMap().entrySet()
            .stream()
            .filter(entry -> entry.getKey().getBaseName().equals(baseName) && entry.getKey().isBetweenInclusive(dateTime))
            .findFirst()
            .map(Map.Entry::getValue);

    if (cached.isPresent()) {
        return cached.get();
    } else {
        final String evaluatedValue = valueLoader.get();
        cache.put(new CachedResult(baseName, intervalCalculator.getInterval(dateTime)), evaluatedValue);
        return evaluatedValue;
    }
}
Другие вопросы по тегам