咨询Kotlin统计名字出现次数代码中空相关错误的原因
Kotlin统计名字出现次数的空值错误问题
我写了一段Kotlin代码用来统计List<Person>集合中名字的出现次数,但运行时触发了空相关错误。明明已经判断名字存在于Map的key集合里才执行自增操作,搞不懂为啥还会出空错误。我刚接触Kotlin,之前用Python的时候从来没遇到过这种空值问题。
代码如下:
data class Person(val name: String, val age: Int) fun checkNameOccurrence(people: List<Person>): Map<String, Int>{ // The map has a key that represents a name and a value of how many times that name is repeated val namesMap: MutableMap<String, Int> = mutableMapOf() for(person in people){ if(person.name in namesMap.keys){ namesMap[person.name] += 1 } namesMap[person.name] = 1 } return namesMap }
问题根源
- 逻辑错误覆盖统计结果:你代码里的
namesMap[person.name] = 1写在if分支外面,不管前面有没有执行自增,最后都会把该名字的计数强制重置为1,这直接让统计逻辑完全失效。 - 空值错误的直接原因:Kotlin的
MutableMap通过[]取值返回的是可空类型(Int?)——编译器会做严格的空安全检查,哪怕你判断过key存在,理论上仍存在并发修改导致key消失的可能(单线程场景下不会真发生,但编译器不认)。不过你的核心问题还是前面的逻辑错误,就算解决空值,统计结果也不对。
修复方案
方案一:修正原逻辑,处理空安全
把赋值namesMap[person.name] = 1放到else分支里,同时用!!处理空值(这里已经判断过key存在,用!!是安全的):
data class Person(val name: String, val age: Int) fun checkNameOccurrence(people: List<Person>): Map<String, Int>{ val namesMap: MutableMap<String, Int> = mutableMapOf() for(person in people){ val name = person.name if(name in namesMap.keys){ namesMap[name] = namesMap[name]!! + 1 } else { namesMap[name] = 1 } } return namesMap }
方案二:用Kotlin便捷API简化代码(推荐)
用getOrDefault方法直接处理默认值,避免空安全判断,代码更简洁:
data class Person(val name: String, val age: Int) fun checkNameOccurrence(people: List<Person>): Map<String, Int>{ val namesMap: MutableMap<String, Int> = mutableMapOf() people.forEach { person -> val name = person.name namesMap[name] = namesMap.getOrDefault(name, 0) + 1 } return namesMap }
方案三:用集合API一键完成统计(最简洁)
Kotlin标准库提供了专门的统计API,一行代码搞定:
data class Person(val name: String, val age: Int) fun checkNameOccurrence(people: List<Person>): Map<String, Int>{ return people.groupingBy { it.name }.eachCount() }
为什么Python没这个问题?
Python字典取值时,key存在返回对应值,不存在返回None,但Python没有编译阶段的空安全检查。而且你原逻辑如果放到Python里,虽然不会触发空值错误,但因为最后赋值覆盖的问题,统计结果同样全是1——只是Python不会像Kotlin一样提前抛出空相关异常而已。
内容的提问来源于stack exchange,提问作者Farner3232
相关产品推荐
相关产品推荐

