在 Kotlin 中,我如何惯用地访问可为 null 的嵌套映射值或 return 默认值?

In Kotlin, how do I idiomatically access nullable nested map values, or return a default?

Quick Kotlin 最佳实践问题,因为我无法真正从文档中找到执行此操作的最佳方法。

假设我有以下嵌套映射(为此问题明确指定输入):

val userWidgetCount: Map<String, Map<String, Int>> = mapOf(
        "rikbrown" to mapOf(
                "widgetTypeA" to 1,
                "widgetTypeB" to 2))

下面的模式能再简洁点吗?

 fun getUserWidgetCount(username: String, widgetType: String): Int {
    return userWidgetCount[username]?.get(widgetType)?:0
}

换句话说,我想 return 用户小部件计数 iff 用户是已知的并且他们有该小部件类型的条目,否则为零。特别是我看到我最初可以使用 [] 语法来访问地图,但是在使用 ?..

之后我看不到在第二级执行此操作的方法

我会为此使用扩展运算符方法。

// Option 1
operator fun <K, V> Map<K, V>?.get(key: K) = this?.get(key)
// Option 2
operator fun <K, K2, V> Map<K, Map<K2, V>>.get(key1: K, key2: K2): V? = get(key1)?.get(key2)

选项 1:

定义一个扩展,为可空映射提供 get 运算符。在 Kotlin 的标准库中,这种方法与 Any?.toString() 扩展方法一起出现。

fun getUserWidgetCount(username: String, widgetType: String): Int {
    return userWidgetCount[username][widgetType] ?: 0
}

选项 2:

为地图的地图创建一个特殊的扩展。在我看来,它更好,因为它显示 map of maps 的合同比连续两个 get 更好。

fun getUserWidgetCount(username: String, widgetType: String): Int {
    return userWidgetCount[username, widgetType] ?: 0
}