Reputation: 1288
Say I have some data in a Seq in Scala 2.10.2, e.g:
scala> val data = Seq( 1, 2, 3, 4, 5 )
data: Seq[Int] = List(1, 2, 3, 4, 5)
Now, I perform some operations and convert it to a Map
scala> val pairs = data.map( i => i -> i * 2 )
pairs: Seq[(Int, Int)] = List((1,2), (2,4), (3,6), (4,8), (5,10))
scala> val pairMap = pairs.toMap
pairMap: scala.collection.immutable.Map[Int,Int] = Map(5 -> 10, 1 -> 2, 2 -> 4, 3 -> 6, 4 -> 8)
Now say, for performance reasons, I'd like pairMap
to use the HashMap
implementation of Map
. What's the best way to achieve this?
Ways I've considered:
Casting:
pairMap.asInstanceOf[scala.collection.immutable.HashMap[Int,Int]]
This seems a bit horrible.
Manually converting:
var hm = scala.collection.immutable.HashMap[Int,Int]()
pairMap.foreach( p => hm += p )
But this isn't very functional.
Using the builder
scala.collection.immutable.HashMap[Int,Int]( pairMap.toSeq:_* )
This works, but it's not the most readable piece of code.
Is there a better way that I'm missing? If not, which of these is the best approach?
Upvotes: 0
Views: 101
Reputation: 13008
You can combine
map
: Map key and value into a tuplebreakOut
: "Break out" the sequence of tuples from map
, and create the target type directlylike this
val s = Seq.range(1, 6)
val m: scala.collection.immutable.HashMap[Int, Int] =
s.map(n => (n, n * n))(scala.collection.breakOut)
which creates the HashMap
on-the-fly without an intermediate map.
By using breakOut
and the explicit result type an appropriate builder for map
is chosen, and your target type is created directly
Upvotes: 0
Reputation: 2205
Interesting bit: it already is an immutable HashMap.
scala> val data = Seq( 1, 2, 3, 4, 5 )
data: Seq[Int] = List(1, 2, 3, 4, 5)
scala> val pairs = data.map( i => i -> i * 2 )
pairs: Seq[(Int, Int)] = List((1,2), (2,4), (3,6), (4,8), (5,10))
scala> val pairMap = pairs.toMap
pairMap: scala.collection.immutable.Map[Int,Int] =
Map(5 -> 10, 1 -> 2, 2 -> 4, 3 -> 6, 4 -> 8)
scala> pairMap.getClass
res0: Class[_ <: scala.collection.immutable.Map[Int,Int]] =
class scala.collection.immutable.HashMap$HashTrieMap
Note: casting to be a hashmap doesn't at all change the underlying thing. If you wanted to guarantee building a hashmap (or some specific type), then I'd recommend this:
scala> import scala.collection.immutable
import scala.collection.immutable
scala> val pairMap = immutable.HashMap(pairs: _*)
pairMap: scala.collection.immutable.HashMap[Int,Int] =
Map(5 -> 10, 1 -> 2, 2 -> 4, 3 -> 6, 4 -> 8)
If you're looking for performance improvements you should look into using a mutable.HashMap
or java.util.HashMap
. Most of scala's collections are out-performed by the native java.util
collections.
Upvotes: 4