Java的Map.merge的Kotlin等价物

jtw3ybtb  于 2022-12-27  发布在  Kotlin
关注(0)|答案(2)|浏览(121)

我正在学习KotlinMultiplatform,并试图将我的一个玩具项目(最初是为JVM编写的)迁移到Kotlin Native。有一件事我一直在使用Java方法Map.merge:

@Test
    fun usingMerge() {
        val map = mutableMapOf("A" to 42, "B" to 13)
        map.merge("A", 20, ::max)
        map.merge("B", 15, ::max)
        map.merge("C", 10, ::max)
        val expected = mapOf("A" to 42, "B" to 15, "C" to 10)
        assertEquals(expected, map)
    }

由于这个Java方法在KotlinNative中不可用,我试图找到一个合适的替代方法。我所得到的代码太冗长,效率太低:

@Test
    fun withoutMerge() {
        val map = mutableMapOf("A" to 42, "B" to 13)
        map["A"].also { if (it == null || it < 20) map["A"] = 20 }
        map["B"].also { if (it == null || it < 15) map["B"] = 15 }
        map["C"].also { if (it == null || it < 10) map["C"] = 10 }
        val expected = mapOf("A" to 42, "B" to 15, "C" to 10)
        assertEquals(expected, map)
    }

有没有一种方法可以写得更短(接近merge的简洁程度),没有重复(例如,在上面的代码中,“A”和20重复了两次),并且不对同一个键执行两次查找?

pu82cl6c

pu82cl6c1#

您可以在MutableMap接口上将自己的merge编写为纯Kotlinextension function
这对你的例子很有效,当然泛型会更复杂一些:

fun MutableMap<String, Int>.merge2(k: String, v: Int, f: (Int, Int)->Int) {
    if (this.containsKey(k)){
        this[k]=f(this.getValue(k), v)
    } else {
        this[k]=v
    }
}

fun main() {
    val map = mutableMapOf("A" to 42, "B" to 13)
    map.merge2("A", 20, Math::max)
    map.merge2("B", 15, Math::max)
    map.merge2("C", 10, Math::max)
}
1bqhqjot

1bqhqjot2#

fun <T, U> MutableMap<T, U>.mergeWith(key: T, value: U, fn: (U, U) -> U) {
  val v = this[key]
  this[key] = if (v == null) value else fn(v, value)
}

val map = mutableMapOf("A" to 42, "B" to 13)

map.mergeWith("A", 20, Math::max)
map.mergeWith("B", 15, Math::max)
map.mergeWith("C", 10, Math::max)

map.forEach(::println)

相关问题