Java 如何实现最近使用的缓存

Java 如何实现最近使用的缓存,java,algorithm,caching,java-me,mru,Java,Algorithm,Caching,Java Me,Mru,实现最近使用的对象缓存的最佳方法是什么 以下是要求和限制 对象存储为键/值对象/对象对,因此接口有点像哈希表get/put 调用“get”会将该对象标记为最近使用的对象 可以随时从缓存中清除最近使用最少的对象 查找和清除必须是快速的(如哈希表fast) 对象的数量可能很大,因此列表查找不够好 实现必须使用JavaME,因此使用第三方代码或标准Java库中的整洁库类的空间很小。因此,我更多地寻找算法答案,而不是现成解决方案的建议 为什么要实施已经实施的东西?使用 然而,如果第三方库完全不可能,我

实现最近使用的对象缓存的最佳方法是什么

以下是要求和限制

  • 对象存储为键/值对象/对象对,因此接口有点像哈希表get/put
  • 调用“get”会将该对象标记为最近使用的对象
  • 可以随时从缓存中清除最近使用最少的对象
  • 查找和清除必须是快速的(如哈希表fast)
  • 对象的数量可能很大,因此列表查找不够好
  • 实现必须使用JavaME,因此使用第三方代码或标准Java库中的整洁库类的空间很小。因此,我更多地寻找算法答案,而不是现成解决方案的建议

    • 为什么要实施已经实施的东西?使用

      然而,如果第三方库完全不可能,我想您正在寻求实现一种类似以下内容的数据结构:

      • 基本上是一个HashMap(扩展
        HashMap
        ,如果愿意的话)
      • 贴图中的每个值都指向排序列表中的一个对象,该列表基于哪个对象使用最多
      • 最近使用的对象将添加到列表的标题-
        O(1)
      • 清除最近最少使用的数据意味着截断列表的结尾-
        O(1)
      • 仍然提供地图查找,但仍然首先保留最近使用的项目
      Java集合提供了开箱即用的功能,非常适合构建缓存。您可能在Java ME中没有此功能,但您可以在此处获取源代码:

      如果你不能直接复制粘贴它,那么看看它就可以开始在你的移动应用程序中实现一个。基本思想就是通过地图元素包含一个链表。如果您在有人放置或获取时保持此更新,则可以有效地跟踪访问顺序和使用顺序

      这些文档包含通过重写该方法来构建MRU缓存的说明。您真正需要做的就是创建一个扩展
      LinkedHashMap
      的类,并像这样重写该方法:

      private static final int MAX_ENTRIES = 100;
      
      protected boolean removeEldestEntry(Map.Entry eldest) {
         return size() > MAX_ENTRIES;
      }
      
      还有一个允许您指定类是按插入顺序还是按使用顺序存储内容的方法,因此您的逐出策略也有一点灵活性:

      public LinkedHashMap(int initialCapacity,
                           float loadFactor,
                           boolean accessOrder)
      

      对于使用顺序,传递true;对于插入顺序,传递false

      另一种方法可能是查看Brian Goetz在《Java并发实践》中的第5.6节:“构建高效、可伸缩的结果缓存”。看一看记忆工具,尽管您可能需要为自己的目的定制它


      另一方面,我不明白为什么Java没有现成的ConcurrentLinkedHashMap。此数据结构将非常有助于构建缓存。

      由于锁定要求,很难构建ConcurrentLinkedHashMap。带有锁的LinkedHashMap很简单,但并不总是有效。并发版本将尝试通过锁拆分或理想情况下使CAS操作使锁定非常便宜来减少锁定量。如果CAS操作确实变得昂贵,那么类似地,桶分割也会有所帮助。由于LRU需要对每个访问操作进行写操作,并且使用双链表,因此使用纯CAS操作实现这一点非常困难。我已经尝试过了,但我需要继续完善我的算法。如果您搜索ConcurrentLinkedHashMap,您将看到我的项目页面


      如果javame不支持CAS操作(我希望这是真的),那么基本同步就是您所能做的。对于LHM来说,这可能已经足够好了,因为我只看到服务器端的高线程数存在性能问题。以上答案加1。

      因为我的最后一点。。。这必须使用JavaME在手机上运行。该算法中的问题是,尽管可以快速在hashmap中查找值,但仍然需要在列表中再次查找并将其移动到头部。。。。尽管在写这篇文章时,我突然意识到hashmap中的value对象可以是一个列表节点对象,可以移动到列表头,而不是实际的value对象本身。耶:)得分!(我只是来发布同样的东西。)这看起来非常适合我一直想要实现的东西——谢谢!mru为false,LRUSON专有/机密为true描述的解决方案将是LRU缓存而不是mru。Ben:为什么Java Collections API或Google Collections中没有ConcurrentLinkedHashMap?com.google.common.collect.CustomConcurrentHashMap.Builder是否可以提供帮助?你的项目也很好。Julien:CCHM是非常新的,不够灵活,似乎是对JBoss的CRHM(Java-7)的反应,对他们的参考地图进行了重写。它似乎主要是定制的CHM。我们有一个用例,锁定正在扼杀我们,所以我只是玩弄了锁拆分的想法,并尝试了CAS。