Scala中合并两个Map[String, Long]的最快方法探讨
合并两个Map并按Key求和的高效实现
你的当前实现虽然能完成功能,但在数据量较大时会有不少额外开销——毕竟要先把两个Map转成Seq,再分组、求和,中间会生成好几个临时集合,还得多次遍历数据。
最快的实现方式:用可变HashMap直接累加
直接用scala.collection.mutable.HashMap来手动遍历两个Map,逐个累加对应Key的Value,是性能最优的方案:
import scala.collection.mutable // 初始化一个空的可变HashMap val sumMap = mutable.HashMap[String, Long]() // 先把第一个Map的所有键值对放进去 for ((key, value) <- m1) { sumMap(key) = value } // 遍历第二个Map,对每个Key做累加 for ((key, value) <- m2) { sumMap(key) = sumMap.getOrElse(key, 0L) + value } // 如果需要不可变的Map,最后转一下就行 val immutableSumMap: Map[String, Long] = sumMap.toMap
为什么这个方法更快?
- 没有多余的中间集合:不用转Seq,也不用groupBy生成临时分组,全程只操作一个HashMap
- 遍历次数最少:每个Map的键值对只被遍历一次,每次的put/get操作都是O(1)的哈希表操作
- 减少对象创建:可变HashMap直接在原结构上修改,不会像不可变Map那样每次更新都生成新节点
使用HashMap确实更高效吗?
没错,不管是可变还是不可变的HashMap,都比你当前的实现高效,尤其是可变HashMap:
- 不可变Map(Scala默认的
Map其实就是不可变HashMap的实现)每次更新都会生成新的结构,频繁修改时会产生大量临时对象,GC压力大 - 可变HashMap直接在原集合上修改,内存开销更低,操作速度更快
如果你坚持要用不可变风格的代码,也可以用foldLeft优化,但性能会比可变版本稍差:
val sumMap = m2.foldLeft(m1) { case (acc, (key, value)) => acc + (key -> acc.getOrElse(key, 0L) + value) }
这个方法避免了转Seq,但本质还是不断创建新的不可变Map,数据量大时不如可变HashMap高效。
内容的提问来源于stack exchange,提问作者Dariusz Krynicki
相关产品推荐
相关产品推荐

