12

我目前正在滚动我自己的小 ORM,并且发现自己面临着创建规范化映射的任务,以防止从数据库中多次加载相同的实体。

我目前的方法是使用HashMap<Object, WeakReference<Object>>. 键是映射数据库实体的主键(ArrayList<Object>如果它是复合键),值为WeakReference<Object>.

我的主要问题是如何清理地图?当不再使用对象时,映射中的弱引用将消失null,我只会在下一次查找时发现它(或者永远不会,如果我不再查找该对象)。我可以让弱引用ReferenceQueue在它们被清除时注册,然后每次查找时检查该队列。清除的引用不会给我任何关于哪个对象被清除的提示,所以我想我必须子类WeakReference化以将键存储在映射中,所以我可以在清除引用后删除它。

这是要走的路,还是有更简单的方法来实现它?

4

1 回答 1

16

我建议使用 Guava 的MapMaker或 r10 中的CacheBuilder

它们允许基于时间和大小的自动驱逐,以及支持弱键或值。(即将推出的CacheBuilder承诺是专门针对这种用例量身定制的。)

所以你可以初始化你的地图:

ConcurrentMap<Key, Object> cache = new MapMaker()
        .weakValues()
        .makeMap();

直接的好处是当一个值被垃圾收集时,整个条目将被删除。此外,您可以使用计算图:

ConcurrentMap<Key, Object> cache = new MapMaker()
        .weakValues()
        .makeComputingMap(loadFunction);

哪里loadFunctionFunction<Key, Object>从数据库加载对象的。这样做的好处是地图将处理特定对象的并发请求,确保查询只被调用一次。此外,请求代码只需要调用get()并且总是可以期望返回对象,无论是来自缓存还是数据库。

这些示例正在使用MapMaker-我还没有玩弄过的乐趣CacheBuilder

有关更多示例,请参阅我的问题我的理想缓存使用番石榴。那篇文章讨论了如何将基于时间的驱逐与规范化结合起来。

于 2011-09-15T20:01:28.417 回答