Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to populate java.util.HashMap on the fly from Scala code?

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?

like image 553
Nermin Serifovic Avatar asked Oct 01 '10 22:10

Nermin Serifovic


People also ask

How does HashMap work in Scala?

HashMap is a part of Scala Collection's. It is used to store element and return a map. A HashMap is a combination of key and value pairs which are stored using a Hash Table data structure. It provides the basic implementation of Map.

How do I convert a HashMap to a Scala Map?

Converting HashMap to Map In Scala, we can convert a hashmap to a map using the tomap method. Explanation: In the above code, we have created a HashMap and then convert it to a Map using the toMap method.

What is difference between Map and HashMap in Scala?

Key Differences between Map and HashMapThe Map is an interface, and HashMap is a class of the Java collection framework. The Map interface can be implemented by using its implementing classes. In comparison, the HashMap class implements the Map interface. The Map contains unique key-pair values.

How do you add a string value to a Map?

put() method of HashMap is used to insert a mapping into a map. This means we can insert a specific key and the value it is mapping to into a particular map. If an existing key is passed then the previous value gets replaced by the new value.


1 Answers

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.

like image 114
Rex Kerr Avatar answered Oct 17 '22 07:10

Rex Kerr