如何从 Scala 代码动态填充 java.util.HashMap?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3843445/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to populate java.util.HashMap on the fly from Scala code?
提问by Nermin Serifovic
I am unit testing java code from ScalaTest and would like to populate a java.util.HashMap within the same statement it gets declared. Is it possible to do this in Scala?
我正在对来自 ScalaTest 的 java 代码进行单元测试,并希望在声明的同一语句中填充 java.util.HashMap。可以在 Scala 中做到这一点吗?
回答by Rex Kerr
There are a bunch of different ways to accomplish this, only some of which have appeared in the answers thus far.
有很多不同的方法可以实现这一点,到目前为止,只有其中一些出现在答案中。
Method One:Since java.util.HashMaphas the constructor HashMap(Map<? extends K,? extends V> m), you could pass it a valid Java Map. And you can do this trivially with Scala's helpful JavaConversions:
方法一:既然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}
The downsides here are that you have to already have a Scala map (slightly wasteful if you're just going to create a Java one, perhaps), and that you have to specify the types. But it's compact and painless.
这里的缺点是你必须已经有一个 Scala 映射(如果你只是要创建一个 Java 映射,可能有点浪费),并且你必须指定类型。但它紧凑且无痛。
Method Two:Alternatively, you can create a new code block as the declaration statement, so you don't even need to have JavaConversionsavailable:
方法二:或者,您可以创建一个新的代码块作为声明语句,这样您甚至不需要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}
Slightly less compact, but completely general, and as efficient (or inefficient) as you care to make it.
稍微不那么紧凑,但完全通用,并且与您想要的一样高效(或低效)。
Method Three:Also, you can create an anonymous subclass of HashMap as long as it's okay to have a subclass (i.e. .getClasswon't return java.util.HashMap), and use the initializer to set your values:
方法三:另外,你可以创建一个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
scala> jmap3.getClass.getSuperclass.getName
res1: java.lang.String = java.util.HashMap
The downside is, of course, that it's a subclass of HashMaprather than HashMap, but it's more compact than the assignment-from-code-block version since you don't need to assign the new map to a val.
当然,缺点是它是HashMap而不是的子类HashMap,但它比从代码块赋值的版本更紧凑,因为您不需要将新映射分配给 val。
Method Four:And finally, of course, you can create a method that does what you want and call it instead:
方法四:最后,当然,您可以创建一个执行您想要的操作的方法并改为调用它:
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}
This is barely less compact than the others and gets the types correct without you having to specify them, so it can be an appealing choice if you're doing this more than once.
这几乎不比其他人紧凑,并且无需指定它们即可正确获取类型,因此如果您不止一次这样做,它可能是一个吸引人的选择。
P.S. Just for fun, I've shown a variety of ways of getting some key-value pairs into the map, but they're not specific to a given method (except for #1 which requires a map). Mix and match at your preference.
PS 只是为了好玩,我已经展示了将一些键值对放入地图的各种方法,但它们并不特定于给定的方法(除了需要地图的 #1)。根据您的喜好混合搭配。
回答by Dave Griffith
You could do the map as an anonymous class, and do the initialization as part of the instance initialization of the object.
您可以将映射作为匿名类进行,并作为对象实例初始化的一部分进行初始化。
import java.util.HashMap
val jhm = new HashMap[String, Int](){
put(key1, value1)
put(key2, value2)
}
This actually works equally well in Java (except for requiring double-braces {{}}), but is much more idiomatic in Scala.
这实际上在 Java 中同样有效(除了需要双大括号 {{}}),但在 Scala 中更为惯用。
回答by huynhjl
Building on Randall's answer, you can use JavaConversionsto help a bit.
以兰德尔的回答为基础,您可以使用JavaConversions一些帮助。
import collection.JavaConversions.asMap
import java.util.HashMap
val jhm = new HashMap[Int,String](Map(1->"one", 2->"two"))
回答by Randall Schulz
All the methods and constructors of java.util.HashMapare available to you, of course, but that does not provide a way to initialize a map unless you have another one to supply the initial values. The closest you're probably going to get is:
java.util.HashMap当然,您可以使用 的所有方法和构造函数,但这并不能提供初始化映射的方法,除非您有另一个方法来提供初始值。您可能会得到的最接近的是:
import java.util.HashMap
val jhm = new HashMap[String, Int]
?code to add key-value pairs to jhm?
回答by Bill K
To make something reusable it would be possible to create a new "Map" subtype just for initialization syntax.
为了使某些东西可重用,可以为初始化语法创建一个新的“Map”子类型。
It could work something like this (I'm ignoring generics because I don't use them regularly and I'd probably get something wrong):
它可以像这样工作(我忽略了泛型,因为我不经常使用它们,而且我可能会出错):
HashMap hm=new HashMap(
new InitMap(
new String[]{"one", "two", "three"},
new int[] { 1 , 2 , 3 };
)
);
There would be more code involved in the InitMap class but it would be reusable and fairly straight-forward (I really like array initialization syntax for this kind of stuff).
InitMap 类中会涉及更多代码,但它是可重用且相当直接的(我真的很喜欢这种东西的数组初始化语法)。
Thinking about it, the InitMap class wouldn't be too hard. You'd probably want to figure out which methods were called and just implement those. Chances are it would only call the KeySet and EntrySet methods.
想想看,InitMap 类不会太难。您可能想弄清楚调用了哪些方法并实现这些方法。它可能只会调用 KeySet 和 EntrySet 方法。
Of course at this rate you could simple create a helper method that took the two arrays and returned a HashMap or extend HashMap and add a new constructor...
当然,以这种速度,您可以简单地创建一个辅助方法,该方法接受两个数组并返回一个 HashMap 或扩展 HashMap 并添加一个新的构造函数......

