Scala双层Map同键合并咨询:Aerospike配置映射聚合实现
Scala嵌套Map自定义合并实现方案
核心问题:你当前使用的++运算符遇到相同key时会直接覆盖旧值,无法满足嵌套合并、同key拼接值的需求,需要自定义两层Map的合并逻辑。
第一步:定义RecoverBins拼接逻辑
根据业务需求实现两个RecoverBins的拼接,示例实现如下:
// 假设你的RecoverBins定义是这样的 case class RecoverBins(bins: List[String]) // 拼接两个RecoverBins def concatRecoverBins(a: RecoverBins, b: RecoverBins): RecoverBins = { RecoverBins(a.bins ++ b.bins) }
第二步:实现内层Map合并逻辑
合并Map[AerospikeSet, RecoverBins]类型的Map,相同Set对应的RecoverBins自动拼接:
def mergeInnerMaps( map1: Map[AerospikeSet, RecoverBins], map2: Map[AerospikeSet, RecoverBins] ): Map[AerospikeSet, RecoverBins] = { map2.foldLeft(map1) { case (acc, (set, bins)) => acc.updatedWith(set) { case Some(existingBins) => Some(concatRecoverBins(existingBins, bins)) case None => Some(bins) } } }
如果是Scala 2.13以前版本不支持updatedWith,可以替换为以下实现:
def mergeInnerMaps( map1: Map[AerospikeSet, RecoverBins], map2: Map[AerospikeSet, RecoverBins] ): Map[AerospikeSet, RecoverBins] = { map2.foldLeft(map1) { case (acc, (set, bins)) => acc + (set -> acc.get(set).map(concatRecoverBins(_, bins)).getOrElse(bins)) } }
第三步:实现外层Map合并逻辑
合并Map[AerospikeNamespace, Map[AerospikeSet, RecoverBins]]类型的Map,相同Namespace对应的内层Map自动合并:
def mergeOuterMaps( map1: Map[AerospikeNamespace, Map[AerospikeSet, RecoverBins]], map2: Map[AerospikeNamespace, Map[AerospikeSet, RecoverBins]] ): Map[AerospikeNamespace, Map[AerospikeSet, RecoverBins]] = { map2.foldLeft(map1) { case (acc, (ns, innerMap)) => acc.updatedWith(ns) { case Some(existingInner) => Some(mergeInnerMaps(existingInner, innerMap)) case None => Some(innerMap) } } }
第四步:修改原有函数的合并逻辑
把原来foldLeft中使用的++替换为mergeOuterMaps即可:
private[this] def extractAerospikeBinsFromKafkaConnectorResource(connectors: List[KafkaConnector]): Map[AerospikeNamespace, Map[AerospikeSet, RecoverBins]] = { connectors.foldLeft(Map.empty[AerospikeNamespace, Map[AerospikeSet, RecoverBins]]) { case (acc, connector) => val singleNsMap = TopicsConfig .parseYaml(connector.getSpec.getConfig.get("config-yaml").toString) .topics .values .map(topicConfig => topicConfig.mapping.namespace.value -> Map(topicConfig.mapping.set.value -> RecoverBins(topicConfig.mapping.bins))) .toMap mergeOuterMaps(acc, singleNsMap) } }
效果验证
用你给出的输入测试:
val m1 = Map("namespace" -> Map("test-recovery-set-double" -> RecoverBins(List("SingleBin")))) val m2 = Map("namespace" -> Map("test-recovery-set-double" -> RecoverBins(List("MultiBin")))) val m3 = Map("namespace" -> Map("test-recovery-set-multi" -> RecoverBins(List("MultiBin")))) val m4 = Map("namespace2" -> Map("test-recovery-set-other" -> RecoverBins(List("SingleBin")))) val result = List(m1, m2, m3, m4).foldLeft(Map.empty[String, Map[String, RecoverBins]])(mergeOuterMaps)
输出结果和要求完全一致:
Map( namespace -> Map( test-recovery-set-double -> RecoverBins(List(SingleBin, MultiBin)), test-recovery-set-multi -> RecoverBins(List(MultiBin)) ), namespace2 -> Map(test-recovery-set-other -> RecoverBins(List(SingleBin))) )
内容的提问来源于stack exchange,提问作者Zvi Mints
相关产品推荐
相关产品推荐

