Scala中的LRUCache?

14

我知道Guava有一個優秀的快取庫,但我正在尋找更適合Scala/函數式編程的庫,我可以做像cache.getOrElse(query, { /* expensive operation */})這樣的操作。我也看了一下Scalaz的Memo,但它沒有lru到期功能。


那个问题与这个问题非常接近。 - om-nom-nom
cache.get(Key, Callable<Value>) 和你想做的有什么区别?只是你想传递一个函数而不是一个Callable吗? - Emil L
是的,我想传递一个函数而不是可调用对象。并且我想要 Map.scala 的所有函数好处。 - pathikrit
2个回答

17

Spray团队有一个spray-caching模块,它使用Futures。有一个普通的LRU版本和一个版本,允许您指定显式的生存时间,在此之后条目将自动过期。

使用Futures显然允许您编写不阻塞的代码。但真正酷的是,它作为奖励解决了“雷鸣般的群体”问题。例如,一堆请求同时到达缓存中没有的相同条目。在天真的缓存实现中,100个线程可能会在缓存中错过该条目,然后跑去生成该缓存条目的相同数据,但是当然,99%都是浪费的努力。您真正想要的是只有一个线程去生成数据,所有100个请求者都可以看到结果。如果您的缓存包含Futures,则这会非常自然地发生:第一个请求者立即在缓存中安装Future,因此只有第一个请求者错过。所有100个请求者都获得了生成结果的Future。


7
基于Java LinkedHashMap实现的LRUCache解决方案,作为Scala mutable.Map暴露。
import java.util.Collections.synchronizedMap

import scala.collection.JavaConversions._
import scala.collection.mutable

class LRUCache[K, V](maxEntries: Int)
  extends java.util.LinkedHashMap[K, V](100, .75f, true) {

  override def removeEldestEntry(eldest: java.util.Map.Entry[K, V]): Boolean 
     = size > maxEntries

}

object LRUCache {
  def apply[K, V](maxEntries: Int): mutable.Map[K, V] 
    = synchronizedMap(new LRUCache[K, V](maxEntries))
}

当映射表大小大于最大条目数时,将删除最近使用的条目。
对于LRU策略,应将LinkedHashMap的第三个构造函数参数设置为true。 LinkedHashMap(int initialCapacity, float loadFactor, boolean accessOrder) 使用示例:
val cache = LRUCache[String, Int](1000)
val key = "key1"
val value = 111

cache.get(key) shouldBe None
cache += key -> value
cache.get(key) shouldBe Some(value)
cache(key) shouldBe value

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接