我知道Guava有一個優秀的快取庫,但我正在尋找更適合Scala/函數式編程的庫,我可以做像cache.getOrElse(query, { /* expensive operation */})
這樣的操作。我也看了一下Scalaz的Memo,但它沒有lru到期功能。
Spray团队有一个spray-caching模块,它使用Futures。有一个普通的LRU版本和一个版本,允许您指定显式的生存时间,在此之后条目将自动过期。
使用Futures显然允许您编写不阻塞的代码。但真正酷的是,它作为奖励解决了“雷鸣般的群体”问题。例如,一堆请求同时到达缓存中没有的相同条目。在天真的缓存实现中,100个线程可能会在缓存中错过该条目,然后跑去生成该缓存条目的相同数据,但是当然,99%都是浪费的努力。您真正想要的是只有一个线程去生成数据,所有100个请求者都可以看到结果。如果您的缓存包含Futures,则这会非常自然地发生:第一个请求者立即在缓存中安装Future,因此只有第一个请求者错过。所有100个请求者都获得了生成结果的Future。
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))
}
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
cache.get(Key, Callable<Value>)
和你想做的有什么区别?只是你想传递一个函数而不是一个Callable吗? - Emil LMap.scala
的所有函数好处。 - pathikrit