我有一个scala方法,如:
import collection.JavaConversions._
def foo(message: Map[String, Any]) {
// message is implicitly converted to Java format
someJavaApi.method1(message)
message.get("mapField") match {
case Some(mapField) =>
val stringValue = mapField.asInstanceOf[Map[String, String]].get("internalField")
otherJavaApi.method(stringValue)
case None => /* do something */
}
}
其中message是具有以下结构的地图:
Map(
"field" -> "value",
"mapField"-> Map("internalField"->"someValue")
)
从上面的代码可以明显看出,我有兴趣从“mapField”字典对象的“internalField”中提取“someValue”
但我一直在运行时收到错误,如:
scala.collection.JavaConversions$JMapWrapper cannot be cast to scala.collection.immutable.Map
我觉得是因为在调用第一个java库API时从scala到java集合的隐式转换,但我不确定,我想建议如何改进String值的提取“someValue “来自”mapField“,采用更多功能或Scala-ish方式,避免异常。
我正在使用scala 2.9.2版本。
答案 0 :(得分:2)
Java映射是可变的,因此它们的Scala包装器是可变的.Map,而不是immutable.Map。
scala> Map("field" -> "value","mapField"-> Map("internalField"->"someValue"))
res0: scala.collection.immutable.Map[String,Object] = Map(field -> value, mapField -> Map(internalField -> someValue))
scala> import collection.JavaConverters._
import collection.JavaConverters._
scala> res0.mapValues { case m: Map[_,_] => m.asJava case x => x }
res2: scala.collection.immutable.Map[String,Object] = Map(field -> value, mapField -> {internalField=someValue})
scala> res0.asJava
res3: java.util.Map[String,Object] = {field=value, mapField=Map(internalField -> someValue)}
scala> .asScala
res4: scala.collection.mutable.Map[String,Object] = Map(field -> value, mapField -> Map(internalField -> someValue))
scala> .foreach { case (k, v: collection.Map[_,_]) => println(v.toList) case _ => }
List((internalField,someValue))
一些安全方面的帮助:
scala> :edit res0
+Map("field" -> Left("value"),"mapField"-> Right(Map("internalField"->"someValue")))
res6: scala.collection.immutable.Map[String,Product with Serializable with scala.util.Either[String,scala.collection.immutable.Map[String,String]]] = Map(field -> Left(value), mapField -> Right(Map(internalField -> someValue)))
scala> .mapValues { case Left(s) => s.length case Right(m) => m.values.map(_.length).sum }
res7: scala.collection.immutable.Map[String,Int] = Map(field -> 5, mapField -> 9)
答案 1 :(得分:0)
我尝试用你的代码制作一个有效的例子:
import collection.JavaConversions._
object Test extends App {
object someJavaApi {
def method1(message: java.util.Map[_, _]) { }
}
object otherJavaApi {
def method(s: String) { }
}
def foo(message: Map[String, Any]) {
// message is implicitly converted to Java format
someJavaApi.method1(message)
message.get("mapField") match {
case Some(mapField) =>
val stringValue = mapField.asInstanceOf[Map[String, String]]("internalField")
otherJavaApi.method(stringValue)
case None => /* do something */
}
}
val message = Map(
"field" -> "value",
"mapField" -> Map("internalField" -> "someValue")
)
foo(message)
}
运行没有错误。
但我不知道如何在不编译代码的情况下回答这个问题。