Java 在Guava缓存中查找间隔中的记录
我正在用SpringSpel计算一些结果,我想缓存这些结果,这样我就不必用相同的参数计算表达式 我的缓存密钥对象:Java 在Guava缓存中查找间隔中的记录,java,caching,guava,google-guava-cache,Java,Caching,Guava,Google Guava Cache,我正在用SpringSpel计算一些结果,我想缓存这些结果,这样我就不必用相同的参数计算表达式 我的缓存密钥对象: @Data @AllArgsConstructor public class CachedResult { private String baseName; private Interval interval; public boolean isBetweenInclusive(final DateTime date) { return i
@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);
}
}
查找包含给定日期时间的间隔为的记录的解决方案:
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)
方法,这样它就可以在需要时将值放入缓存本身,但我想不出一种方法来利用is介于inclusive
和此方法之间
我试图在评论中指出我遇到的问题:
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.put(new CachedResult(…)
将记录放入缓存中
有没有比调用asMap
并像映射一样过滤缓存更好的方法?我是否可以使用cache.get(key,valueLoader)
或GuavasCacheLoader
自动输入值
随着演出的进行,我一次最多会有5-10条记录,但我会从中读到很多东西,因此,读取时间对我来说非常重要,我不确定我当前的实现是否是最好的方法,即始终迭代5-10条记录并检查每一条记录。在阅读Louis的评论后,我的最终解决方案写道:
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;
}
}
public String getFileName(最终字符串baseName、最终日期时间DateTime、最终供应商值加载器){
最终可选缓存=cache.asMap().entrySet()
.stream()
.filter(entry->entry.getKey().getBaseName().equals(baseName)和&entry.getKey().isBetweenInclusive(dateTime))
.findFirst()
.map(map.Entry::getValue);
if(cached.isPresent()){
返回cached.get();
}否则{
最终字符串evaluatedValue=valueLoader.get();
put(新的CachedResult(baseName,intervalCalculator.getInterval(dateTime)),evaluatedValue);
返回评估值;
}
}
;对5-10条记录进行迭代将非常快,基本上其他任何记录都会比较慢(而且可能没有更好的方法)。调用asMap
后对映射项进行迭代是否会对过期产生不同于调用缓存的影响。get
会吗?换句话说,如果缓存中有1条记录,这两个调用是否相同:cache.asMap().entrySet().stream().findFirst().get().getValue()代码>cache.get(记录)代码>
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;
}
}