Guava MapMaker可选择为工厂方法设置maximumSize(0)?

时间:2011-06-09 07:04:43

标签: java guava

我正在使用MapMaker在我的应用程序中实现数据对象的缓存:

public class DataObjectCache<DO extends MyDataObject> {

    private final ConcurrentMap<String, DO> innerCache;

    public DataObjectCache(Class<DO> doClass) {

        Function<String, DO> loadFunction = new Function<String, DO>() {
            @Override
            public DO apply(String id) {
                //load and return DO instance
            }
        };

        innerCache = new MapMaker()
             .softValues()
             .makeComputingMap(loadFunction);
    }

    private DO getDataObject(String id) {
        return innerCache.get(id);
    }

    private void putDataObject(DO dataObject) {
        innerCache.putIfAbsent(dataObject.getID(), dataObject);
    }
}

将为每个数据对象类实例化其中一个DataObjectCaches,并将它们保存在主映射中,使用Class对象作为键。

有少数数据对象类,其实例我不想缓存。但是,我仍然希望它们可以通过函数调用的相同代码进行实例化,并且在加载它们时仍然需要并发性。

在这些情况下,我想知道我是否可以将地图的最大大小设置为0,以便立即驱逐条目,但仍然利用地图的原子计算方面。这是一个好主意吗?低效?

修改

我意识到如果我在加载后立即驱逐条目,就无法保证它们被明显加载 - 如果Map没有跟踪它们,那么具有相同ID的对象的多个实例可能会浮动在环境。所以我没有这样做,我认为我会使用弱值而不是软值来表示我不想占用缓存的对象类型 - 如果有人对此有任何意见,请告诉我。

2 个答案:

答案 0 :(得分:2)

根据您的编辑,听起来您正在寻找的是一个内部人。 interner返回一个代表性实例; Interner.intern将根据您的equals方法为所有相等的对象返回相同的对象。来自Javadoc:

  

选择并返回代表   任何一个集合的实例   每个实例等于每个实例   其他。如果给出两个相等的输入   对于这种方法,两个调用都将返回   相同的实例。那是,   实习生(a).equals(a)总是持有,和   实习生(a)==实习生(b)当且仅当   a.equals(b)中。注意实习生(a)是   允许现在返回一个实例   以后如果是另一个实例   原来的实习案例是   垃圾收集。

请参阅http://guava-libraries.googlecode.com/svn/trunk/javadoc/com/google/common/collect/Interner.htmlhttp://guava-libraries.googlecode.com/svn/trunk/javadoc/com/google/common/collect/Interners.html

那就是说,当你说你不希望它被缓存时,这取决于你的意思。如果你真的想每次都返回一个新实例,那么你必须有多个等效对象实例“浮动”。

Interning正在持有一个实例(因此它可以返回相同的实例),因此它仍然是一种缓存。我想知道你为什么要避免缓存。如果是因为物体的大小,你可以使用弱的内部物;当不再引用GC时,该实例将可用于GC。然后,简单地使用具有弱值的MapMaker地图也可以实现这一点。

另一方面,如果您不想缓存的原因是因为您的数据可能会发生变化,那么实习可能就是您的答案。我想你想要的是每次检索对象,然后实习它。如果对象等于缓存的对象,则interner将只返回现有实例。如果不同,则interner将缓存新的。那么您的责任就是在对象上编写一个equals方法,该方法符合使用新的实例与实例的要求。

答案 1 :(得分:0)

好吧,MapMaker.maximumSize有这一行:checkArgument(size > 0, "maximum size must be positive"),这将使这个变得不可能。 expireAfter方法也需要积极的论据。很明显,API设计人员不希望您以这种方式使用他们的MapMaker制作的地图。

那就是说,我想,如果你真的想要使用缓存作为直通,你可以使用1纳秒的expireAfterWrite。这是一个黑客,但实际上会产生同样的效果。