I'm trying to write a method which takes a Map[K, Collection[V]] and converts it to a map with a different type of Collection for its values. The method takes the "multimap" and a builder that will construct the new collections. I use it like this:
val multimap = new java.util.HashMap[Int, java.util.List[String]]
multimap.put(1, Arrays.asList("One"))
multimap.put(2, Arrays.asList("Two", "Three"))
val mapOfLists: java.util.Map[Int, java.util.Set[String]] =
asMap(multimap, Builder.SET)
Here's what the builder looks like:
trait Builder[C[_] <: java.util.Collection[_]]
{
def create[V]: C[V]
}
object Builder
{
val SET = new Builder[java.util.Set]()
{
def create[V]: java.util.Set[V] = new java.util.HashSet[V]
}
}
Here's the implementation of asMap(). It works but I don't understand - why do I need the type cast at the end?
def asMap[K, V, C[_] <: java.util.Collection[_]](
multimap: java.util.Map[K, _ <: java.util.Collection[V]], builder: Builder[C]): java.util.Map[K, C[V]] =
{
val result = new java.util.HashMap[K, C[V]]
val iterator: Iterator[K] = multimap.keySet.iterator
while (iterator.hasNext)
{
val key = iterator.next
val collection: C[V] = builder.create[V]
collection.asInstanceOf[java.util.Collection[V]].addAll(multimap.get(key))
result.put(key, collection)
}
result
}
Without the type case I get this error:
[ERROR] error: type mismatch;
[INFO] found : java.util.Collection[V]
[INFO] required: java.util.Collection[_ <: _$2] where type _$2
[INFO] collection.addAll(multimap.get(key))
You accidentally created existential types instead of type constructors. A valid type constructor would be C[X] <: Collection[X|
so you need to change Builder
to
trait Builder[C[X] <: Collection[X]] {
def create[V]: C[V]
}
and the signature of asMap
to
def asMap[K, V, C[X] <: Collection[X]](multimap: Map[K, _ <: Collection[V]],
builder: Builder[C]): Map[K, C[V]]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With