如何从Scala代码动态填充java.util.HashMap?

我是从ScalaTestunit testingjava代码,并希望在声明它的同一语句中填充java.util.HashMap。 可以在Scala中执行此操作吗?

有许多不同的方法可以实现这一点,到目前为止只有一些方法出现在答案中。

方法一:由于java.util.HashMap具有构造函数HashMap(Map m) ,因此可以向其传递有效的Java Map。 你可以使用Scala有用的JavaConversions来做到这JavaConversions

 scala> import scala.collection.JavaConversions._ import scala.collection.JavaConversions._ scala> val myMap = Map(1->"Hi",2->"Bye") myMap: scala.collection.immutable.Map[Int,java.lang.String] = Map((1,Hi), (2,Bye)) scala> val jmap = new java.util.HashMap[Int,String](myMap) // Need explicit types jmap: java.util.HashMap[Int,String] = {1=Hi, 2=Bye} 

这里的缺点是你必须已经有一个Scala映射(如果你打算创建一个Java,可能会有点浪费),并且你必须指定类型。 但它紧凑而无痛。

方法二:或者,您可以创建一个新的代码块作为声明语句,因此您甚至不需要JavaConversions可用:

 scala> val jmap2 = { | val x = new java.util.HashMap[Int,String] | for ((k,v) <- List(1->"Howdy",2->"partner")) x.put(k,v) | x | } jmap2: java.util.HashMap[Int,String] = {1=Howdy, 2=partner} 

略微不那么紧凑,但完全一般,并且像你想要的那样有效(或低效)。

方法三:另外,你可以创建一个HashMap的匿名子类,只要它有一个子类(即.getClass不会返回java.util.HashMap ),并使用初始值设置你的值:

 scala> val jmap3 = new java.util.HashMap[Int,String] { | put(1,"Yo"); put(2,"bro") | } jmap3: java.util.HashMap[Int,String] = {1=Yo, 2=bro} scala> jmap3.getClass.getName res0: java.lang.String = $anon$1 scala> jmap3.getClass.getSuperclass.getName res1: java.lang.String = java.util.HashMap 

当然,缺点是它是HashMap的子类而不是HashMap ,但它比从代码块分配版本更紧凑,因为您不需要将新映射分配给val。

方法四:最后,当然,您可以创建一个方法来执行您想要的操作并改为调用它:

 scala> def newJHM[A,B](kv: Iterable[(A,B)]) = { | val jhm = new java.util.HashMap[A,B] | kv.foreach(i => jhm.put(i._1,i._2)) | jhm | } newJHM: [A,B](kv: Iterable[(A, B)])java.util.HashMap[A,B] scala> val jmap4 = newJHM(Seq(1->"Bye",2->"Now")) // Type inference now works jmap4: java.util.HashMap[Int,java.lang.String] = {1=Bye, 2=Now} 

这几乎不像其他人那么紧凑,并且在不必指定它们的情况下获得正确的类型,因此如果您不止一次这样做,它可能是一个有吸引力的选择。

PS为了好玩,我已经展示了将一些键值对添加到地图中的各种方法,但它们并不特定于给定的方法(#1需要地图除外)。 根据您的喜好混合搭配。

您可以将映射作为匿名类进行,并将初始化作为对象实例初始化的一部分进行。

 import java.util.HashMap val jhm = new HashMap[String, Int](){ put(key1, value1) put(key2, value2) } 

这实际上在Java中同样有效(除了需要双括号{{}}),但在Scala中更为惯用。

基于Randall的答案,您可以使用JavaConversions来帮助我。

 import collection.JavaConversions.asMap import java.util.HashMap val jhm = new HashMap[Int,String](Map(1->"one", 2->"two")) 

当然, java.util.HashMap所有方法和构造函数都可供您使用,但除非您有另一个提供初始值,否则它不提供初始化映射的方法。 你可能会得到的最接近的是:

 import java.util.HashMap val jhm = new HashMap[String, Int] «code to add key-value pairs to jhm» 

为了使某些东西可重用,可以为初始化语法创建一个新的“Map”子类型。

它可以像这样工作(我忽略了generics因为我不经常使用它们而且我可能会出错):

 HashMap hm=new HashMap( new InitMap( new String[]{"one", "two", "three"}, new int[] { 1 , 2 , 3 }; ) ); 

在InitMap类中会涉及更多的代码,但它可以重用并且非常直接(我真的很喜欢这种东西的数组初始化语法)。

想一想,InitMap类不会太难。 您可能想要确定调用哪些方法并实现它们。 有可能它只会调用KeySet和EntrySet方法。

当然,按照这个速度你可以简单地创建一个辅助方法,它接受两个数组并返回一个HashMap或扩展HashMap并添加一个新的构造函数……