I'm aware of this question for java, but none of those implementations seem to play well with scala.collection.JavaConversions
.
I'm looking for something simple (e.g. single file, not a whole library) that implements SoftHashMap
such that it plays well with Scala Map
(i.e. supports getOrElseUpdate
, unzip
, and the remaining Scala Map
methods).
Implementation inspired by this java WeakHashMap
:
import scala.collection.mutable.{Map, HashMap}
import scala.ref._
class SoftMap[K, V <: AnyRef] extends Map[K, V]
{
class SoftValue[K, +V <: AnyRef](val key:K, value:V, queue:ReferenceQueue[V]) extends SoftReference(value, queue)
private val map = new HashMap[K, SoftValue[K, V]]
private val queue = new ReferenceQueue[V]
override def += (kv: (K, V)): this.type =
{
processQueue
val sv = new SoftValue(kv._1, kv._2, queue)
map(kv._1) = sv
this
}
private def processQueue
{
while (true)
{
queue.poll match
{
case Some(sv:SoftValue[K, _]) => map.remove(sv.key)
case _ => return
}
}
}
override def get(key: K): Option[V] = map.get(key) match
{
case Some(sv) => sv.get match
{ case v:Some[_] => v
case None => {map.remove(key); None} }
case None => None
}
override def -=(key: K):this.type =
{
processQueue
map.remove(key)
this
}
override def iterator: Iterator[(K, V)] =
{
processQueue
map.iterator.collect{ case (key, sv) if sv.get.isDefined => (key, sv.get.get) }
}
override def empty:SoftMap[K, V] = new SoftMap[K, V]
override def size = {processQueue; map.size}
}