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

发布于 2024-09-25 22:57:51 字数 91 浏览 1 评论 0原文

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

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

悲凉≈ 2024-10-02 22:57:51

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

方法一:由于java.util.HashMap具有构造函数HashMap(Map 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}

这与其他方法相比几乎不那么紧凑,并且无需指定即可获得正确的类型,因此如果您多次这样做,这可能是一个有吸引力的选择。

PS 只是为了好玩,我展示了将一些键值对放入映射中的各种方法,但它们并不特定于给定方法(除了需要映射的#1)。根据您的喜好混合搭配。

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.HashMap has 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:

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.

Method Two: Alternatively, you can create a new code block as the declaration statement, so you don't even need to have JavaConversions available:

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. .getClass won't return java.util.HashMap), and use the initializer to set your values:

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

The downside is, of course, that it's a subclass of HashMap rather 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.

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.

拥抱没勇气 2024-10-02 22:57:51

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

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

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

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.

羁客 2024-10-02 22:57:51

基于 Randall 的答案,您可以使用 JavaConversions 来提供一些帮助。

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

Building on Randall's answer, you can use JavaConversions to help a bit.

import collection.JavaConversions.asMap
import java.util.HashMap
val jhm = new HashMap[Int,String](Map(1->"one", 2->"two"))
坠似风落 2024-10-02 22:57:51

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

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

All the methods and constructors of java.util.HashMap are 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:

import java.util.HashMap
val jhm = new HashMap[String, Int]
«code to add key-value pairs to jhm»
圈圈圆圆圈圈 2024-10-02 22:57:51

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

它可以像这样工作(我忽略泛型,因为我不经常使用它们,我可能会出错):

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

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

想想看,InitMap 类也不会太难。您可能想弄清楚调用了哪些方法并实现这些方法。它很可能只会调用 KeySet 和 EntrySet 方法。

当然,按照这个速度,您可以简单地创建一个辅助方法,该方法获取两个数组并返回一个 HashMap 或扩展 HashMap 并添加一个新的构造函数...

To make something reusable it would be possible to create a new "Map" subtype just for initialization syntax.

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).

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.

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...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文