Conversione implicita tra le raccolte java e scala utilizzando JavaConversions

Ho unito una scala Set di scala Map usando una funzione generica

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

Questo gestisce il caso quando c’è uno scontro di chiavi uguali. Tuttavia, volevo farlo con le raccolte Java nel codice Scala. Ho ricercato un po ‘e JavaConversions incontrato JavaConversions . L’ho importato e l’ho scritto

 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  a + (if (a.contains(kv._1)) kv._1 -> f(a(kv._1), kv._2) else kv) } 

Tuttavia, dice che c’è una mancata corrispondenza di tipo

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

JavaConversions non è utilizzato per convertire implicitamente util.HashMap in mutable.Map ? Cosa mi manca qui?

Dicono di provare JavaConverters, poiché JavaConversions è deprecato.

 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) } :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) } ^ :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) } ^ :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) } ^ :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) } :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] 

Forse per mostrare perché è deprecato:

 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) } :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) } ^ :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)) { ^ 

Notando che per la comprensione produce un insieme di coppie.

 scala> def mergeMaps[A, B](ms: Set[Map[A, B]])(f: (B, B) => B) = for (m <- ms; kv <- m) yield kv mergeMaps: [A, B](ms: Set[Map[A,B]])(f: (B, B) => B)scala.collection.immutable.Set[(A, B)] 

Apparentemente l'inferenza non riesce a fare la conversione e quindi a capire i tipi di operazione.

Qualche volta a pezzi l'espressione aiuta l'inferenza, ma non qui.

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

Un JavaConverter farebbe quello che vuoi?

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