繁体   English   中英

如何优雅地创建 map 在 Kotlin 中只有非空值

[英]how to elegantly create a map with only non-null values in Kotlin

如何在不必求助于 MutableMap 并转换为不可变 map 的情况下重写此代码?

fun createMap(mandatoryValue: String, optionalValue: String?): Map<String, String> {
    val map = mutableMapOf("key1" to mandatoryValue)
    optionalValue?.let { map.put("key2", it) }
    return map.toMap()
}

我的替代解决方案也不是很好,因为它需要一个不安全的演员表:

fun createMap(mandatoryValue: String, optionalValue: String?): Map<String, String> =
    mapOf(
        "key1" to mandatoryValue,
        "key2" to optionalValue
    ).filterValues { it != null } as Map<String, String>

我正在寻找的是以下内容:

fun createMap(mandatoryValue: String, optionalValue: String?): Map<String, String> =
    mapOf(
        "key1" to mandatoryValue,
        optionalValue?.let { "key2" to it }
    )

您可以拥有自己的扩展 function 如下,然后使用它从Map过滤 null 值:

fun <K, V> Map<K, V?>.filterValuesNotNull() = 
    mapNotNull { (k, v) -> v?.let { k to v } }.toMap()

toMap()不一定会创建不可变的 map。 它只保证是只读的。 底层 class 实例可能是一个 MutableMap(如果它有多个键,则在当前实现中为真)。 因此,您的第一个代码块中的toMap()是不必要的。 当您返回 MutableMap 时,它会自动向上转换为 Map,因为您将 Map 指定为返回类型。 所以,你可以把

fun createMap(mandatoryValue: String, optionalValue: String?): Map<String, String> {
    val map = mutableMapOf("key1" to mandatoryValue)
    optionalValue?.let { map.put("key2", it) }
    return map
}

或者

fun createMap(mandatoryValue: String, optionalValue: String?): Map<String, String> =
    mutableMapOf("key1" to mandatoryValue).apply {
        if (optionalValue != null) put("key2", optionalValue)
    }

要获得您在上一个示例中请求的语法,您可以创建一个mapOf重载,它接受并过滤 null 值:

fun <K, V> mapOf(vararg pairs: Pair<K, V>?): Map<K, V> =
    mapOf(*pairs.filterNotNull().toTypedArray())

使用MutableMap没有任何问题——事实上,您的第一个解决方案(没有多余的toMap() )已经非常优雅了。 它比任何不可变的答案都更简单、更清晰。 不可变操作是以额外的 object 创建和复制为代价的,因此,除非您需要保证不变性,否则最好使用MutableMap ,但只能通过Map接口公开它,就像您已经在做的那样。

如果你真的想一成不变地做到这一点,你可以这样做:

fun createMap(mandatoryValue: String, optionalValue: String?): Map<String, String> =
    mapOf("key1" to mandatoryValue) +
        (optionalValue?.let { mapOf("key2" to it) } ?: emptyMap())

或者等效地,如果您愿意:

fun createMap(mandatoryValue: String, optionalValue: String?): Map<String, String> =
    mapOf("key1" to mandatoryValue) +
        if (optionalValue != null) mapOf("key2" to optionalValue) else emptyMap()

或者:

fun createMap(mandatoryValue: String, optionalValue: String?): Map<String, String> {
    val mandatoryMap = mapOf("key1" to mandatoryValue)
    return optionalValue?.let { mandatoryMap + ("key2" to optionalValue) } ?: mandatoryMap
}

或者:

fun createMap(mandatoryValue: String, optionalValue: String?): Map<String, String> {
    val mandatoryMap = mapOf("key1" to mandatoryValue)
    return if (optionalValue != null) mandatoryMap + ("key2" to optionalValue) else mandatoryMap
}

在 kotlin 1.6

buildMap {
    put("key1", mandatoryValue)

    if (optionalValue != null)
        put("key2", optionalValue)
}

这会在工作表下创建一个 mutableMap,但非常优雅且可读 <3

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM