我目前正在滚动自己的小ORM,发现自己面临创建规范化映射的任务,以防止从数据库中多次加载同一实体。
我目前的方法是使用HashMap<Object, WeakReference<Object>>。该键是映射数据库实体的主键(ArrayList<Object>如果是复合键,则为),其值为WeakReference<Object>。
HashMap<Object, WeakReference<Object>>
ArrayList<Object>
WeakReference<Object>
我的主要问题是如何清理地图?当不再使用某个对象时,映射中的弱引用将消失null,而我只会在下一次查找时发现它(或者,如果我不再查找该对象,则永远不会)。当弱引用ReferenceQueue被清除时,我可以将它们注册为a ,然后在每次查找时检查该队列。尽管清除的引用不会给我任何有关清除哪个对象的提示,所以我想我必须继承子类WeakReference才能将键存储在映射中,因此可以在清除引用后将其删除。
null
ReferenceQueue
WeakReference
这是走的路,还是有更简单的方法来实现呢?
我建议在r10中使用Guava的MapMaker或CacheBuilder。
它们允许自动*place)基于时间和大小,驱逐,以及配套的弱密钥或值。(即将发布的CacheBuilder承诺将专门针对此类用例而定制。)
CacheBuilder
因此,您可以初始化地图:
ConcurrentMap<Key, Object> cache = new MapMaker() .weakValues() .makeMap();
而直接的好处是,当一个值被垃圾回收时,整个条目将被删除。此外,您可以使用计算图:
ConcurrentMap<Key, Object> cache = new MapMaker() .weakValues() .makeComputingMap(loadFunction);
其中loadFunction是Function<Key, Object>从数据库加载的对象。这样做的好处是,映射将处理对特定对象的并发请求,从而确保查询仅被调用一次。此外,发出请求的代码只需调用get()即可,并且无论从高速缓存还是从数据库中获取,始终可以期望返回对象。
loadFunction
Function<Key, Object>
get()
这些示例正在使用MapMaker-我还没有玩玩具的乐趣CacheBuilder。
MapMaker