如何正确编写Map<Map<String,Item>,Int>中元素计数的自增代码?
解决嵌套Map实现物品计数器的代码问题
原代码的核心问题
- 类型转换错误:
Pair(i.Name, i) as Map<String, Item>完全不成立,Pair和Map是完全不同的类型,强制转换会直接抛出ClassCastException。 - 使用不可变Map:
mapOf()创建的是不可变Map,无法执行修改、添加操作,必须改用mutableMapOf()。 - 键的匹配逻辑无效:即使能创建
Map作为键,每次循环新建的Map对象(内容相同但引用不同)会导致containsKey()永远无法匹配已存在的键(除非依赖Map的内容相等判断,但这种方式冗余且低效)。
正确实现方案
方案一:直接用Item作为键(推荐)
如果Item类正确实现了equals()和hashCode()(比如基于Name或其他唯一标识属性),直接用Item作为键是最简洁高效的方式:
- 初始化代码:
var Items = mutableMapOf<Item, Int>()
- 计数逻辑代码:
for (item in items) { // 简化写法:用getOrPut自动处理存在/不存在的情况 this.UnitInventory.Items.getOrPut(item) { 0 }++ }
或者用更直观的判断写法:
for (item in items) { val count = this.UnitInventory.Items[item] ?: 0 this.UnitInventory.Items[item] = count + 1 }
方案二:坚持用Map<String, Item>作为键(不推荐)
如果一定要保留原设计思路,需要正确创建Map对象,同时使用可变Map:
- 初始化代码:
var Items = mutableMapOf<Map<String, Item>, Int>()
- 计数逻辑代码:
for (item in items) { val key = mapOf(item.Name to item) // 用getOrPut简化逻辑 this.UnitInventory.Items.getOrPut(key) { 0 }++ }
或者用判断写法:
for (item in items) { val key = mapOf(item.Name to item) if (this.UnitInventory.Items.containsKey(key)) { this.UnitInventory.Items[key] = this.UnitInventory.Items[key]!! + 1 } else { this.UnitInventory.Items[key] = 1 } }
关键说明
getOrPut是Kotlin提供的便捷函数,会先检查键是否存在:存在则返回对应值,不存在则执行lambda初始化值并添加到Map中,非常适合这种计数场景。- 优先选择方案一,因为用
Item作为键更符合语义,避免冗余的Map包装,同时性能更优。
内容的提问来源于stack exchange,提问作者Luckych
相关产品推荐
相关产品推荐

