【问题标题】:How to populate java.util.HashMap on the fly from Scala code?如何从 Scala 代码中动态填充 java.util.HashMap?
【发布时间】:2011-04-20 02:19:37
【问题描述】:

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

【问题讨论】:

    标签: java scala hashmap scalatest


    【解决方案1】:

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

    方法一: 因为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 的子类,但它比 assignment-from-code-block 版本更紧凑,因为您不需要将新地图分配给一个值。

    方法四:最后,当然,你可以创建一个方法来做你想做的事,然后调用它:

    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 中更为惯用。

      【讨论】:

      • 我认为没有对象的静态初始化之类的东西。我猜你指的是实例初始化器,不是吗?
      • 从技术上讲,Scala 没有实例初始化器。您显示的代码正在为匿名内部类执行 构造函数 内的 put 方法。
      【解决方案3】:

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

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

      【讨论】:

        【解决方案4】:

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

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

        【讨论】:

          【解决方案5】:

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

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

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

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

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

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

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2012-10-09
            • 1970-01-01
            • 1970-01-01
            • 2012-11-29
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2023-03-21
            相关资源
            最近更新 更多