2014-10-09 41 views
1

新来斯卡拉 - 如何将Map[String,String]Map[String, Any] 创建Map[String,Any]的值是字符串,但我不知道怎么投或以其他方式要挟“Any”型到“String”型。如何在Scala中从Map [String,Any]创建一个Map [String,String]?

+5

如果你知道他们是字符串,为什么编译器还认为他们是任何? – stew 2014-10-09 04:11:48

+2

'myAny.toString' – elm 2014-10-09 04:20:02

+0

我有一个函数从案例类中检索参数名称和值。它将它们返回为Map [String,Any],因为这些值可以是任何类型。我习惯于Java,我可以将其转换为我想要的类型。我发现我可以使用'Any.asInstanceOf [String]'来获得相同的效果。 – coolgar 2014-10-09 16:15:36

回答

1

正如你所说,你地图上的所有值都是字符串,你可以简单地使用asInstanceOf。如果你的假设是不正确,您将收到运行时异常,如下面所示:

$ scala 
Welcome to Scala version 2.9.2 (OpenJDK 64-Bit Server VM, Java 1.7.0_55). 
Type in expressions to have them evaluated. 
Type :help for more information. 

scala> val m:Map[String, Any] = Map("foo" -> 5, "bar" -> 7.6, "baz" -> "qux") 
m: Map[String,Any] = Map(foo -> 5, bar -> 7.6, baz -> qux) 

scala> val m2: Map[String, Any] = Map("foo" -> "5", "bar" -> "7.6", "baz" -> "qux") 
m2: Map[String,Any] = Map(foo -> 5, bar -> 7.6, baz -> qux) 

scala> m2.asInstanceOf[Map[String, String]] 
res0: Map[String,String] = Map(foo -> 5, bar -> 7.6, baz -> qux) 

这是完美的,当所有的值实际上String类型。

scala> res0("foo") 
res5: String = 5 

当心你的错误的假设:

scala> m.asInstanceOf[Map[String, String]] 
res2: Map[String,String] = Map(foo -> 5, bar -> 7.6, baz -> qux) 

scala> res2("foo") 
java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String 
    at .<init>(<console>:10) 
    at .<clinit>(<console>) 
    at .<init>(<console>:11) 
    at .<clinit>(<console>) 
    at $print(<console>) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
    at java.lang.reflect.Method.invoke(Method.java:606) 
    at scala.tools.nsc.interpreter.IMain$ReadEvalPrint.call(IMain.scala:704) 
    at scala.tools.nsc.interpreter.IMain$Request$$anonfun$14.apply(IMain.scala:920) 
    at scala.tools.nsc.interpreter.Line$$anonfun$1.apply$mcV$sp(Line.scala:43) 
    at scala.tools.nsc.io.package$$anon$2.run(package.scala:25) 
    at java.lang.Thread.run(Thread.java:744) 
2

首先有一个Map[String, Any]是一个标志,可能已经脱轨,虽然没有任何代码可以看,但我不能真正帮助你。通常,当你开始看到Any和推断出的其他超泛型类型时,它就是Scala的类型系统,告诉你你写的代码并不意味着你认为它的意思。

如果你真的要做到这一点,你可以这样做:

scala> val m = Map("foo" -> 5, "bar" -> 7.6, "baz" -> "qux") 
m: scala.collection.immutable.Map[String,Any] = Map(foo -> 5, bar -> 7.6, baz -> qux) 

scala> m.mapValues(_.toString) 
res0: scala.collection.immutable.Map[String,String] = Map(foo -> 5, bar -> 7.6, baz -> qux) 
+0

它并不一定意味着代码已经脱轨,它可能意味着有人不得不在他们的scala代码中使用java库(如ServletRequest参数映射) – 2016-02-10 22:54:16

+0

@AndrewNorman因此“可能”:)我同意有拥有“Any”的正当理由,但我坚持认为它可能表示逻辑错误,并且推断出一些不相关类型的最小上限。 – acjay 2016-02-22 21:22:10

0

Map[String,Any]一个例子由编译器作为推断包括

val a = Map("s" -> 1, "t" -> "w") 
a: scala.collection.immutable.Map[String,Any] = Map(s -> 1, t -> w) 

其中至少常见类型IntStringAny

toString应用于地图中的每个值。

0

正如其他人已经提到的那样,事实上首先有一个Any,这是一个迹象表明某处出了问题。正确的解决方案是找出哪里出了问题并修复它。

不过,如果你真的希望所有的值转换为String秒(这是规避类型系统,这样的话你应该做的事),这里是你如何做到这一点:

val anyMap: Map[String, Any] = Map("foo" -> "bar", "baz" -> "qux") 

val stringMap = anyMap.mapValues(_.asInstanceOf[String]) 
// => stringMap: Map[String, String] = Map(foo -> bar, baz -> qux) 
相关问题