产生map的`mapNotNull`等价于什么?

时间:2019-05-15 12:44:42

标签: kotlin

如下所示,我可以使用List<Int?>函数将List<Int>转换为mapNotNull

    @Test
    fun main() {
        val testData = listOf(1, null, 3, null)
        val noNull = processAwayNull(testData)
    }

    private fun processAwayNull(testData: List<Int?>): List<Int> {
        return testData.mapNotNull{ it }
    }

如何将Map<String, Int?>转换为Map<String, Int>? 下面的testData.filter { it.value != null }无效,因为它仍会产生Map<String, Int?>

    @Test
    fun main() {
        val testData = mapOf("One" to 1, "Two" to null, "Three" to 3, "Four" to null)
        val noNull = processAwayNull(testData)
    }

    private fun processAwayNull(testData: Map<String, Int?>): Map<String, Int> {
        return testData.filter { it.value != null }
    }

1 个答案:

答案 0 :(得分:4)

嗯,不是真的开箱即用(从某种意义上说,您立即获得Map<String, Int>),但是filterValues呢?

testData.filterValues { it != null } // gives Map<String, Int?> but without null-values

将其与mapValues组合或替换(也许您可以使用默认值代替null?)

// combining:
testData.filterValues { it != null }
        .mapValues { (_, value) -> value as Int }
// replacing:
testData.mapValues { (_, value) -> value ?: /* default value */ 0 } 

两者都给出了Map<String, Int>,但是第一个创建并填充了2个地图,第二个使用0而不是null

您还可以使用适当的filterValues来简化unchecked cast变量,因为“我们知道的更好”:

testData.filterValues { it != null } as Map<String, Int> // unchecked cast, because: we really do know better, do we? ;-)

或者,您也可以按照已知的方式处理所有条目(使用mapNotNull),然后根据它创建一个新地图:

testData.asSequence()
        .mapNotNull { (key, value) ->
            value?.let {
              key to it
            }
        }
        .toMap() // giving Map<String, Int>

如果您需要更多的时间,您甚至可能希望拥有自己的扩展功能:

@Suppress("UNCHECKED_CAST")
fun <K, V> Map<K, V?>.filterValuesNotNull() = filterValues { it != null } as Map<K, V>

现在您可以按如下方式使用它:

testData.filterValuesNotNull() // giving Map<String, Int>