【问题标题】:Java Guava combination of Multimap and CacheJava Guava 结合 Multimap 和 Cache
【发布时间】:2012-03-05 12:23:12
【问题描述】:

有没有 Guava 的 CacheMultimap 功能的组合可用?本质上,我需要一个集合,其中条目在给定时间后过期,例如在Cache 中可用,但我有非唯一键,我需要条目独立过期。

【问题讨论】:

    标签: java guava multimap


    【解决方案1】:

    我认为 Louis Wasserman 在上面的其中一个 cmets 中提供了答案,即没有现成的 MultimapCache 组合可用。我已经使用下面伪代码中概述的解决方案解决了我的问题/要求:

    private Cache<Integer,Object> cache = CacheBuilder.newBuilder().SomeConfig.build();
    private Multimap<Integer,Object> multimap = HashMultimap<Integer, Object>.create();
    private AtomicInteger atomicid = new AtomicInteger(0);
    
    public void putInMultimap(int id, Object obj) {
       int mapid = atomicid.addAndGet(1);
       cache.put(mapid,obj);
       multimap.put(id,mapid);
    }
    public List<Object> getFromMultimap(int id) {
       Set<Integer> mapids = multimap.get(id);
       List<Object> list = new ArrayList<Object>();
       for (int i : mapids) {
          list.add(cache.getIfPresent(i));
       }
       return list;
    }
    

    这个简单的“解决方案”有一些限制,但对我来说效果很好。

    【讨论】:

    • 你如何处理不断增长的多地图?
    • @neu242 对于当前答案中的SomeConfig 部分,您可以在此处添加.removalListener 调用,每当从缓存中驱逐某些内容时都会调用该调用,以便您也可以将其从多地图
    【解决方案2】:

    使用 Guava 缓存没有 put 方法,缓存被设计为自填充。从键查找返回的值是在运行时计算的。 Commons Collections Transformer Factories 采用了类似的方法。

    我认为你可以很容易地实现你正在寻找的东西。如果您查看一个简单的 Map 支持的示例,例如 Kitty-Cache,您可以看到您可以将 Map 替换为 Multimap 并相应地重写其他方法。所以在 KittyCache.java 内部你可以有类似的东西:

    Multimap<K, CacheEntry<V>> cache;
    

    这种缓存的诀窍是在有人请求之前没有任何东西真正过期。

    【讨论】:

    • “使用 Guava 缓存没有 put 方法,缓存被设计为自填充”——这不是真的。确实Cache 本身没有“put”方法,并且LoadingCache 被设计为自填充,但您始终可以使用非加载缓存,并调用cache.asMap().put(...) 添加您自己的条目。当然,这不会为您提供多地图。只是更正第一个陈述。
    • 从 Guava 11.0 开始,Cache 中有一个 [put method](docs.guava-libraries.googlecode.com/git/javadoc/com/google/…, V))。您提供的示例很有趣,但我不能依赖请求的过期,我实现 RemovalListener 以在 Cache 中获取过期通知。
    • 感谢您直截了当地介绍 Ray。我在引用:java.dzone.com/articles/google-guava-cache
    • 当然 hgus1294 是对的--put 是在 11.0 中添加的。我的错。
    • 所有这一切都说,Multimap 实现非常重要,我们的内部实现并非旨在处理缓存条目过期。这将是一个相当大的项目。 =/
    【解决方案3】:

    只要您谈论的是Cache 而不是LoadingCache,您就可以将Cache.asMap() 视图传递给Multimaps.newMultimap

    【讨论】:

    • 有趣。我做了一些测试,但我无法让条目独立过期。根据您的建议,我将Cache.asMap() 传递给Multimaps.newMultimap,并在expireAfterWrite 设置为1000 ms 的情况下进行了一些快速测试,并运行了以下场景:map.put(1,Object1);Thread.Sleep(700)map.put(1,Object2);Thread.Sleep(500)。在这一点上,我希望第一个条目被驱逐,但第二个仍然存在,但我发现两个条目都被驱逐了。也许我做错了什么,但除非我能改变行为,否则它对我不起作用。
    猜你喜欢
    • 2019-01-02
    • 2016-02-06
    • 2010-12-07
    • 2012-10-28
    • 2015-04-30
    • 2011-09-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多