You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Kotlin中Map两种取值方式下值的可空性差异原因

Kotlin groupBy返回Map的取值可空性差异问题

我是Kotlin新手,在Android Jetpack Compose初学者课程练习中遇到一个问题:通过groupBy方法得到的LinkedHashMap,使用[]运算符取值时,返回值类型为List?,编译器要求必须进行空安全调用(?.或!!.);而通过forEach遍历该Map时,遍历得到的值类型为List,无需空检查,添加空安全调用还会提示不必要。请问为何两种取值方式下值的可空性会存在差异?

完整代码

enum class Daypart {
    MORNING, AFTERNOON, EVENING
}

data class Event (
    val title: String,
    val description: String? = null,
    val daypart: Daypart,
    val duration: Int
)

fun main() {
    
    val event1 = Event(title = "Wake up", description = "Time to get up", daypart = Daypart.MORNING, duration = 0)
    val event2 = Event(title = "Eat breakfast", daypart = Daypart.MORNING, duration = 15)
    val event3 = Event(title = "Learn about Kotlin", daypart = Daypart.AFTERNOON, duration = 30)
    val event4 = Event(title = "Practice Compose", daypart = Daypart.AFTERNOON, duration = 60)
    val event5 = Event(title = "Watch latest DevBytes video", daypart = Daypart.AFTERNOON, duration = 10)
    val event6 = Event(title = "Check out latest Android Jetpack library", daypart = Daypart.EVENING, duration = 45)
    
    val events = mutableListOf<Event>(event1, event2, event3, event4, event5, event6)
    
    val daypartEvents = events.groupBy {
        it.daypart
    }
    
    print(daypartEvents::class.simpleName)
    
    println("Morning: ${daypartEvents[Daypart.MORNING]?.size}")
    
    daypartEvents.forEach { (daypart, events) ->
        println("$daypart: ${events.size}")
    }
    
}

问题解答

1. Map的[]运算符(get方法)的定义

Kotlin中Map接口的get运算符(也就是你用的[]),方法签名是operator fun get(key: K): V?。这个设计的核心原因是:编译器无法提前确定你传入的key一定存在于Map中——哪怕你的场景里groupBy生成的Map包含了所有枚举值,但从Map的通用定义来看,任何key都可能不存在,所以返回值必须标记为可空类型V?,强制你处理空情况。

2. forEach遍历的逻辑

当你调用Map的forEach方法时,遍历的是Map中实际存在的键值对。forEach的参数是一个接收Map.Entry<K, V>的函数,每个Entry都是Map里已经确认存在的条目,对应的value必然是非空的V,而不是V?。所以在遍历过程中,你拿到的events是确定存在的List<Event>,自然不需要空安全调用。

额外小技巧

如果想避免使用[]时的空检查,可以用getOrDefault方法直接指定默认值:

println("Morning: ${daypartEvents.getOrDefault(Daypart.MORNING, emptyList()).size}")

这样即使key不存在,也会返回一个空列表,无需处理可空性。

内容的提问来源于stack exchange,提问作者Aaron

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 22:27:35