我已经在我的SpringBoot服务之一中实现了这个Guava缓存:
public class CachedMenuServiceImpl implements MenuService {
private LoadingCache<String, MenuChart2> menuChartCache = CacheBuilder.newBuilder()
.maximumSize(15)
.expireAfterAccess(15, TimeUnit.MINUTES)
.build(
new CacheLoader<String, MenuChart2>() {
public MenuChart2 load(String menuSymbol) throws ExecutionException {
return generateCharts (menuSymbol);
}
}
);
@Override
public MenuChart2 getCharts (String menuSymbol) throws ExecutionException {
return menuChartCache.get(menuSymbol);
}
public MenuChart2 generateCharts (String MenuSymbol) throws ExecutionException {
MenuChart2 menuChart2;
…
return menuChart2;
}
public MenuChart2 generateCharts (String menuSymbol) throws ExecutionException {
if (LOG.isDebugEnabled()) {
LOG.debug ("generating charts for {} ", menuSymbol);
}
Menu menu = findBySymbol(menuSymbol).get();
Map<LocalDate, MenuChart2.Statistics> last30DPerDay =
menuPriceByDayService.findAllOrderByUpdateDate(menu, DateUtils.monthlyDate(), 30)
.stream()
.sorted(comparing(MenuPriceByDay::getUpdateDate))
.collect(Collectors
.toMap(MenuPriceByDay::getUpdateLocalDate, p -> new MenuChart2().new Statistics( p.getMinPrice().doubleValue(),
p.getMaxPrice().doubleValue(),
p.getAvgPrice().doubleValue())));
Map<LocalDate, MenuChart2.Statistics> last3MPerDay =
menuPriceByDayService.findAllOrderByUpdateDate(menu, DateUtils.quarterlyDate(), 92)
.stream()
.sorted(comparing(MenuPriceByDay::getUpdateDate))
.collect(Collectors
.toMap(MenuPriceByDay::getUpdateLocalDate, p -> new MenuChart2().new Statistics( p.getMinPrice().doubleValue(),
p.getMaxPrice().doubleValue(),
p.getAvg;
Map<LocalDate, MenuChart2.Statistics> last6MPerDay =
menuPriceByDayService.findAllOrderByUpdateDate(menu, DateUtils.semestralDate(), 26)
.stream()
.sorted(comparing(MenuPriceByDay::getUpdateDate))
.collect(Collectors
.toMap(MenuPriceByDay::getUpdateLocalDate, p -> new MenuChart2().new Statistics( p.getMinPrice().doubleValue(),
p.getMaxPrice().doubleValue(),
p.getAvgPrice().doubleValue())));
Map<LocalDate, MenuChart2.Statistics> last1YPerDay =
menuPriceByDayService.findAllOrderByUpdateDate(menu, DateUtils.yearlylDate(), 52)
.stream()
.sorted(comparing(MenuPriceByDay::getUpdateDate))
.collect(Collectors
.toMap(MenuPriceByDay::getUpdateLocalDate, p -> new MenuChart2().new Statistics( p.getMinPrice().doubleValue(),
p.getMaxPrice().doubleValue(),
p.getAvgPrice().doubleValue())));
Map<LocalDateTime, DoubleSummaryStatistics> priceStatisticsXhour =
menuPriceService.findAll(menu).parallelStream()
.filter(cp -> cp.getUpdateDate().after(DateUtils.yesterday()))
.sorted(comparing(MenuPrice::getUpdateDate))
.collect(Collectors.groupingBy(cp -> cp.getUpdateLocalDateHour(),
Collectors.summarizingDouble(cp -> cp.getPriceInDouble())))
.entrySet().parallelStream().sorted(Map.Entry.comparingByKey())
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue,
(oldValue, newValue) -> oldValue, LinkedHashMap::new));
MenuChart2 menuChart2 = new MenuChart2();
menuChart2.setLas24HPerHour (priceStatisticsXhour);
menuChart2.setLast30DPerDay (last30DPerDay);
menuChart2.setLast1YPerDay (last1YPerDay);
menuChart2.setLast3MPerDay (last3MPerDay);
menuChart2.setLast6MPerDay (last6MPerDay);
return menuChart2;
}
但是当我访问它时,出现此错误:
com.google.common.util.concurrent.UncheckedExecutionException: java.lang.IllegalStateException: Duplicate key com.tdk.api.json.MenuChart2$Statistics@6f377595
at com.google.common.cache.LocalCache$Segment.get(LocalCache.java:2218)
at com.google.common.cache.LocalCache.get(LocalCache.java:4147)
at com.google.common.cache.LocalCache.getOrLoad(LocalCache.java:4151)
at com.google.common.cache.LocalCache$LocalLoadingCache.get(LocalCache.java:5140)
at com.tdk.backend.service.CachedMenuServiceImpl.getCharts(CachedMenuServiceImpl.java:189)
at com.tdk.backend.service.CachedMenuServiceImpl$$FastClassBySpringCGLIB$$2ea84be7.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
...
Caused by: java.lang.IllegalStateException: Duplicate key com.tdk.api.json.MenuChart2$Statistics@6f377595
at java.util.stream.Collectors.lambda$throwingMerger$0(Collectors.java:133)
at java.util.HashMap.merge(HashMap.java:1254)
at java.util.stream.Collectors.lambda$toMap$58(Collectors.java:1320)
at java.util.stream.ReduceOps$3ReducingSink.accept(ReduceOps.java:169)
at java.util.stream.SortedOps$SizedRefSortingSink.end(SortedOps.java:352)
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:482)
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499)
at com.tdk.backend.service.CachedMenuServiceImpl.generateCharts(CachedMenuServiceImpl.java:238)
at com.tdk.backend.service.CachedMenuServiceImpl$1.load(CachedMenuServiceImpl.java:86)
at com.tdk.backend.service.CachedMenuServiceImpl$1.load(CachedMenuServiceImpl.java:84)
at com.google.common.cache.LocalCache$LoadingValueReference.loadFuture(LocalCache.java:3708)
at com.google.common.cache.LocalCache$Segment.loadSync(LocalCache.java:2416)
at com.google.common.cache.LocalCache$Segment.lockedGetOrLoad(LocalCache.java:2299)
at com.google.common.cache.LocalCache$Segment.get(LocalCache.java:2212)
... 101 common frames omitted
答案 0 :(得分:0)
异常似乎不是来自Guava缓存。它似乎是使用流从您那里收集并将其收集到地图中的。当您调用.get(..)
时会发生异常,因为它是LoadingCache
,因此当它在generate方法中运行代码时,就会生成异常。您可能正在做类似
.stream().collect(
Collectors.toMap(o -> someFunctionToGetKey(),
o -> someFunctionToGetValue())
);
但是,在此实现中,您没有提供关于如果生成两个相同密钥会发生什么的逻辑。您需要指定第三个参数,该参数定义遇到重复密钥时要采取的行为。例如,考虑我们有这个基本的pojo
@Data
class Model {
private int id;
private String name;
}
我们有List<Model> list = new ArrayList<>();
您可以执行以下操作:
list.stream()
.collect(Collectors.toMap(
Model::getId,
Model::getName,
(v1,v2) -> v2
));
第三个参数(v2,v2) -> v2
指示收集器如果列表中有两个具有相同ID的条目该怎么做。在此示例中,它仅将name
的最新值用作键id
。