我是从ScalaTest测试java代码的单元,并希望在声明它的同一语句中填充java.util.HashMap。是否可以在Scala中执行此操作?
答案 0 :(得分:25)
有很多不同的方法可以实现这一目标,到目前为止,只有一些方法出现在答案中。
方法一:由于java.util.HashMap
具有构造函数HashMap(Map<? extends K,? extends V> m)
,因此您可以将其传递给有效的Java Map。你可以使用Scala有用的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}
这几乎不像其他人那么紧凑,并且在不必指定类型的情况下获得正确的类型,因此如果您不止一次这样做,它可能是一个有吸引力的选择。
P.S。只是为了好玩,我已经展示了将一些键值对添加到地图中的各种方法,但它们并不特定于给定的方法(除了#1需要地图)。根据您的喜好混合搭配。
答案 1 :(得分:8)
您可以将地图作为匿名类来执行,并将初始化作为对象实例初始化的一部分。
import java.util.HashMap
val jhm = new HashMap[String, Int](){
put(key1, value1)
put(key2, value2)
}
这实际上在Java中同样有效(除了需要双括号{{}}),但在Scala中更为惯用。
答案 2 :(得分:3)
根据Randall的回答,您可以使用JavaConversions
来帮助。
import collection.JavaConversions.asMap
import java.util.HashMap
val jhm = new HashMap[Int,String](Map(1->"one", 2->"two"))
答案 3 :(得分:0)
当然,java.util.HashMap
的所有方法和构造函数都可供您使用,但这并不提供初始化地图的方法,除非您有另一个提供初始值的方法。你可能会得到的最接近的是:
import java.util.HashMap
val jhm = new HashMap[String, Int]
«code to add key-value pairs to jhm»
答案 4 :(得分:0)
为了使某些东西可以重复使用,可以为初始化语法创建一个新的“Map”子类型。
它可以像这样工作(我忽略了泛型因为我不经常使用它们而且我可能会出错):
HashMap hm=new HashMap(
new InitMap(
new String[]{"one", "two", "three"},
new int[] { 1 , 2 , 3 };
)
);
InitMap类中会涉及更多代码,但它可以重用并且相当简单(我真的很喜欢这种东西的数组初始化语法)。
考虑到这一点,InitMap类不会太难。您可能想要确定调用哪些方法并实现它们。有可能它只会调用KeySet和EntrySet方法。
当然按照这个速度你可以简单地创建一个辅助方法,它接受两个数组并返回一个HashMap或扩展HashMap并添加一个新的构造函数......