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

2022-09-02 19:28:37

我正在对ScalaTest的java代码进行单元测试,并希望在它声明的同一语句中填充java.util.HashMap。在Scala中可以做到这一点吗?


答案 1

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

方法一:既然有构造函数,你可以给它一个有效的Java Map。你可以用Scala的帮助来轻松做到这一点:java.util.HashMapHashMap(Map<? extends K,? extends V> m)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的匿名子类,只要可以有一个子类(即 不会返回 ),并使用初始值设定项设置值:.getClassjava.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

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

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

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}

这几乎不比其他类型更紧凑,并且无需指定它们即可获得正确的类型,因此,如果您多次执行此操作,则可能是一个吸引人的选择。

附言:只是为了好玩,我已经展示了各种方法,可以将一些键值对放入地图中,但它们并不特定于给定的方法(除了#1需要地图)。根据您的喜好混搭。


答案 2

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

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

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