2010-08-04 2 views
6

Tôi đang cố gắng viết một phương thức lấy Map [K, Collection [V]] và chuyển nó thành một bản đồ với một loại Collection khác cho các giá trị của nó. Phương thức này lấy "multimap" và một builder sẽ xây dựng các collection mới. Tôi sử dụng nó như thế này:Scala type constructors hiểu lầm

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) 

Đây là những gì những người xây dựng trông giống như:

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] 
    } 
} 

Đây là việc thực hiện các asMap(). Nó hoạt động nhưng tôi không hiểu - tại sao tôi cần loại truyền ở cuối?

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 
} 

Nếu không có trường hợp loại I nhận được lỗi này:

[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)) 

Trả lời

8

Bạn vô tình tạo ra các dạng tồn tại thay vì loại nhà xây dựng. Một constructor loại hợp lệ sẽ C[X] <: Collection[X| vì vậy bạn cần phải thay đổi Builder để

trait Builder[C[X] <: Collection[X]] { 
    def create[V]: C[V] 
} 

và chữ ký của asMap để

def asMap[K, V, C[X] <: Collection[X]](multimap: Map[K, _ <: Collection[V]], 
    builder: Builder[C]): Map[K, C[V]]