I am pretty new to Scala and still do not understand generics that well. Consequently, I cannot figure out why the compiler hates me with type mismatch errors.
I am using Google's Guava library to create some simple caches represented as Scala's ConcurrentMap. I would like to keep track of the created caches using another Map of cache name to ConcurrentMap (the cache). Here is what I have so far which compiles but is missing the tracking of the caches (I've commented out the bits that fail):
import scala.collection.mutable.ConcurrentMap
trait CacheManager {
def getCache[V <: AnyRef](
cacheName: String,
cacheListener: Option[CacheListener] = None): ConcurrentMap[String, V]
}
import scala.collection.JavaConversions._
import com.google.common.collect.MapMaker
import java.util.concurrent.{ConcurrentMap => JConcurrentMap, TimeUnit}
import org.slf4j.LoggerFactory
import com.google.common.cache.{RemovalNotification, RemovalListener, CacheBuilder}
import scala.collection.mutable.ConcurrentMap
class LocalCacheManager extends CacheManager {
private val logger = LoggerFactory.getLogger(classOf[LocalCacheManager])
private val caches /*: ConcurrentMap[String, ConcurrentMap[String, _ <: AnyRef]]*/ =
asScalaConcurrentMap[String, ConcurrentMap[String, _ <: AnyRef]](
new MapMaker().concurrencyLevel(4).makeMap[String, ConcurrentMap[String, _ <: AnyRef]]())
def getCache[V <: AnyRef](cacheName: String, cacheListener: Option[CacheListener] = None) = {
// caches.getOrElseUpdate(cacheName, {
val cache = CacheBuilder.newBuilder()
.concurrencyLevel(4)
.softValues()
.expireAfterAccess(30, TimeUnit.MINUTES)
.build[String, V]()
asScalaConcurrentMap[String, V](cache.asMap())
// })
}
}
Basically, if I try to add the Guava cache to caches (via the commented out caches.getOrElseUpdate) then the compiler complains with the following:
error: type mismatch;
found : scala.collection.mutable.ConcurrentMap[String,_$1] where type _$1 <: AnyRef
required: scala.collection.mutable.ConcurrentMap[String,V]
caches.getOrElseUpdate(cacheName, {