Skip to content

Instantly share code, notes, and snippets.

@apivovarov
Last active December 6, 2016 22:55
Show Gist options
  • Save apivovarov/d3beae60c2b3896e8cf0ea646960455a to your computer and use it in GitHub Desktop.
Save apivovarov/d3beae60c2b3896e8cf0ea646960455a to your computer and use it in GitHub Desktop.
MapMerger
import scala.collection._
import scala.collection.immutable.HashMap
def time(times: Int)(fn: => Unit)(name: String): Unit = {
val t1 = System.currentTimeMillis()
var i = 0
while (i < times) {
fn
i += 1
}
val t2 = System.currentTimeMillis()
println(s"$name: ${t2 - t1}")
}
val N = 100000
val a = (0 to 100).map(x => (x.toString, x)).toMap
val b = (70 to 120).map(x => (x.toString, x)).toMap
// Merge immutable using foldLeft and Map + (k, v)
def mergeB[A, B](a: Map[A, B], b: Map[A, B])(mergef: (B, Option[B]) => B): Map[A, B] = {
val (big, small) = if (a.size > b.size) (a, b) else (b, a)
small.foldLeft(big) { case (z, (k, v)) => z + (k -> mergef(v, z.get(k))) }
}
def merge1[A](a: Map[A, Int], b: Map[A, Int]): Map[A, Int] =
mergeB(a, b)((v1, v2) => v2.map(_ + v1).getOrElse(v1))
// Merge using Seq.groupBy
def merge2[A](a: Map[A, Int], b: Map[A, Int]): Map[A, Int] = {
(a.toSeq ++ b.toSeq).groupBy(_._1).mapValues(_.map(_._2).sum)
}
// Merge mutable Maps
def merge3[A](a: mutable.Map[A, Int], b: mutable.Map[A, Int]): mutable.Map[A, Int] = {
val (big, small) = if (a.size > b.size) (a, b) else (b, a)
small.foreach { case(k, v) =>
val v2 = big.get(k)
if (v2.isEmpty) big.update(k, v)
else big.update(k, (v2.get + v))
}
big
}
// Merge immutable maps using mutable Map
def merge4[A](a: Map[A, Int], b: Map[A, Int]): Map[A, Int] = {
val (big, small) = if (a.size > b.size) (a, b) else (b, a)
val bigM = mutable.Map[A, Int](big.toSeq: _*)
small.foreach { case(k, v) =>
val v2 = big.get(k)
if (v2.isEmpty) bigM.update(k, v)
else bigM.update(k, (v2.get + v))
}
bigM
}
// Merge maps using HashMap.merged
def merge5[K](a: HashMap[K, Int], b: HashMap[K, Int]): HashMap[K, Int] = {
a.merged(b)((a, b) => (a._1, a._2 + b._2))
}
// TESTS
time(N)(merge1(a, b))("Merge immutable using foldLeft and Map + (k, v)") // 710
time(N)(merge2(a, b))("Merge using Seq.groupBy") // 3437
val am = mutable.Map(a.toSeq: _*)
val bm = mutable.Map(b.toSeq: _*)
time(N)(merge3(am, bm))("Merge mutable Maps") // 361
time(N)(merge4(a, b))("Merge immutable maps using mutable Map") // 1480
val ahm = HashMap(a.toSeq: _*)
val bhm = HashMap(b.toSeq: _*)
time(N)(merge5(ahm, bhm))("HashMap merged") // 283
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment