2016-07-12 7 views
0

fusionierte ich ein scala Set von scala Map s eine generische FunktionImplizite Konvertierung zwischen Java und scala Sammlungen mit JavaConversions

def mergeMaps[A, B](ms: Set[Map[A, B]])(f: (B, B) => B): Map[A, B] = 
(Map[A, B]() /: (for (m <- ms; kv <- m) yield kv)) 
{ 
    (a, kv) => 
    a + (if (a.contains(kv._1)) kv._1 -> f(a(kv._1), kv._2) else kv) 
} 

Dieser behandelt den Fall, wenn ein Zusammenstoß der gleichen Tasten besteht. Allerdings wollte ich es mit Java-Sammlungen in Scala Code machen. Ich recherchierte ein bisschen und stieß auf JavaConversions. Ich kann es importiert und schrieb dieses

def mergeMaps[A, B](ms: Set[Map[A, B]])(f: (B, B) => B): Map[A, B] = 
(new util.HashMap[A, B] /: (for (m <- ms; kv <- m) yield kv)) 
{ 
    case (a, kv) => 
    a + (if (a.contains(kv._1)) kv._1 -> f(a(kv._1), kv._2) else kv) 
} 

Aber es sagt, dass es ein Typenkonflikt

Error:(67, 11) type mismatch; 
found : scala.collection.mutable.Map[A,B] 
required: java.util.HashMap[A,B] 
    a + (if (a.contains(kv._1)) kv._1 -> f(a(kv._1), kv._2) else kv) 
    ^

Ist das nicht JavaConversions implizit verwendet wird, ist util.HashMap zu mutable.Map konvertieren? Was fehlt mir hier?

Antwort

2

Sie sagen, JavaConverter zu versuchen, da JavaConversions veraltet ist.

scala> import collection.JavaConverters._ 
import collection.JavaConverters._ 

scala> def mergeMaps[A, B](ms: Set[Map[A, B]])(f: (B, B) => B): Map[A, B] = 
    | (new java.util.HashMap[A, B] /: (for (m <- ms; kv <- m) yield kv)) { 
    | case (a, kv) => a + (if (a.contains(kv._1)) kv._1 -> f(a(kv._1), kv._2) else kv) } 
<console>:16: error: value contains is not a member of java.util.HashMap[A,B] 
     case (a, kv) => a + (if (a.contains(kv._1)) kv._1 -> f(a(kv._1), kv._2) else kv) } 
           ^
<console>:16: error: java.util.HashMap[A,B] does not take parameters 
     case (a, kv) => a + (if (a.contains(kv._1)) kv._1 -> f(a(kv._1), kv._2) else kv) } 
                  ^
<console>:16: error: type mismatch; 
found : (A, B) 
required: String 
     case (a, kv) => a + (if (a.contains(kv._1)) kv._1 -> f(a(kv._1), kv._2) else kv) } 
                        ^
<console>:15: error: type mismatch; 
found : java.util.HashMap[A,B] 
required: Map[A,B] 
     (new java.util.HashMap[A, B] /: (for (m <- ms; kv <- m) yield kv)) { 
            ^

scala> def mergeMaps[A, B](ms: Set[Map[A, B]])(f: (B, B) => B): Map[A, B] = 
    | (new java.util.HashMap[A, B].asScala /: (for (m <- ms; kv <- m) yield kv)) { 
    | case (a, kv) => a + (if (a.contains(kv._1)) kv._1 -> f(a(kv._1), kv._2) else kv) } 
<console>:15: error: type mismatch; 
found : scala.collection.mutable.Map[A,B] 
required: scala.collection.immutable.Map[A,B] 
     (new java.util.HashMap[A, B].asScala /: (for (m <- ms; kv <- m) yield kv)) { 
              ^

scala> def mergeMaps[A, B](ms: Set[Map[A, B]])(f: (B, B) => B): Map[A, B] = 
    | (new java.util.HashMap[A, B].asScala.toMap /: (for (m <- ms; kv <- m) yield kv)) { 
    | case (a, kv) => a + (if (a.contains(kv._1)) kv._1 -> f(a(kv._1), kv._2) else kv) } 
mergeMaps: [A, B](ms: Set[Map[A,B]])(f: (B, B) => B)Map[A,B] 

Vielleicht zu zeigen, warum es veraltet ist:

scala> def mergeMaps[A, B](ms: Set[Map[A, B]])(f: (B, B) => B): Map[A, B] = 
    | (new java.util.HashMap[A, B] /: (for (m <- ms; kv <- m) yield kv)) { 
    | case (a, kv) => a + (if (a.contains(kv._1)) kv._1 -> f(a(kv._1), kv._2) else kv) } 
<console>:19: error: type mismatch; 
found : scala.collection.mutable.Map[A,B] 
required: java.util.HashMap[A,B] 
     case (a, kv) => a + (if (a.contains(kv._1)) kv._1 -> f(a(kv._1), kv._2) else kv) } 
         ^
<console>:18: error: type mismatch; 
found : java.util.HashMap[A,B] 
required: Map[A,B] 
     (new java.util.HashMap[A, B] /: (for (m <- ms; kv <- m) yield kv)) { 
            ^

Anbetracht dessen, dass die für das Verständnis eines Satzes von Paaren ergibt.

Scheinbare Inferenz versäumt, sowohl die Konvertierung und dann herauszufinden, die OP-Typen.

Manchmal hilft das Auseinanderbrechen des Ausdrucks, aber nicht hier.

scala> def mergeMaps[A, B](ms: Set[Map[A, B]])(f: (B, B) => B): Map[A, B] = { 
    | val ss = for (m <- ms; kv <- m) yield kv 
    | (new java.util.HashMap[A, B] /: ss) { 
    | case (a, kv) => a + (if (a.contains(kv._1)) kv._1 -> f(a(kv._1), kv._2) else kv) } 
    | } 
+0

Veraltet? Ich finde keine Erwähnung in den [Docs] (http://www.scala-lang.org/api/current/#scala.collection.JavaConversions$) oder der [Quelle] (https: // github. com/scala/scala/blob/v2.11.8/src/library/scala/Sammlung/JavaConversions.scala # L1). – jwvh

+0

Ich habe den Vorteil, dass ich vor kurzem die Abwertung beigetragen habe: http://www.scala-lang.org/api/2.12.0-M5/scala/collection/JavaConversions$.html –

+0

@jwvh Ich erinnere mich, dass es auch ein bisschen ist Verbesserung in den Dokumenten, da die meisten Verbesserungen inkrementell sind: http://www.scala-lang.org/api/2.12.0-M5/scala/collection/JavaConverters$.html –

5

Würde ein JavaConverter tun, was Sie wollen?

scala> import scala.collection.JavaConverters._ 
import scala.collection.JavaConverters._ 

scala> val x = (new java.util.HashMap[Int,Int]).asScala 
x: scala.collection.mutable.Map[Int,Int] = Map() 
+0

Ja würde es! ... –

Verwandte Themen