Android Kotlin中mapOf的containsKey返回false问题排查求助
Kotlin Map匹配异常问题:containsKey返回false但日志显示key存在
我编写了一段将String映射到自定义GetInvitationError类的Kotlin代码,在Kotlin Playground中可正常通过key获取对应值,但在实际项目代码中无法实现:containsKey返回false,getInvitationErrors[errorCode]返回null。相关代码与日志如下:
data class GetInvitationError( val message: String, val cta: String? = null ) val getInvitationErrors: Map<String, GetInvitationError> = mapOf( "ERR_GINV_601" to GetInvitationError(message = "the invitation does not exist"), // Nothing To Do - No Action Needed NAN "ERR_GINV_602" to GetInvitationError(message = "error occured when getting information about organization", cta = "Try again"), "ERR_GINV_603" to GetInvitationError(message = "the invitation is no longer active"), // NAN "ERR_GINV_604" to GetInvitationError(message = "the invitation is outdated"), // NAN "ERR_GINV_605" to GetInvitationError(message = "error when encoding the response", cta = "Try again"), "ERR_GINV_606" to GetInvitationError(message = "the invited member is not the signed member", cta = "Sign Out"), "ERR_GINV_607" to GetInvitationError(message = "error when encoding the response", cta = "Try again"), "ERR_GINV_608" to GetInvitationError(message = "error when encoding the response", cta = "Try again") ) @Composable fun ErrorEncoded(errorCode: String) { Log.d("ErrorEncoded", "code $errorCode") var giError: GetInvitationError? = null try { Log.d("ERRORENCODED", getInvitationErrors.toString()) Log.d("ErrorEncoded", "COntainsKey : ${getInvitationErrors.containsKey(errorCode)}") giError = getInvitationErrors[errorCode]!! Log.d("ErrorEncoded", "Getting value : $giError") } catch(e: Exception) { Log.d("ErrorEncoded", e.message, e.cause) } Scaffold {} }
日志信息
2023-05-26 06:01:42.516 2352-2352 ErrorEncoded com. D code ERR_GINV_601 2023-05-26 06:01:42.516 2352-2352 ERRORENCODED com. D {ERR_GINV_601=GetInvitationError(message=the invitation does not exist, cta=null), ERR_GINV_602=GetInvitationError(message=error occured when getting information about organization, cta=Try again), ERR_GINV_603=GetInvitationError(message=the invitation is no longer active, cta=null), ERR_GINV_604=GetInvitationError(message=the invitation is outdated, cta=null), ERR_GINV_605=GetInvitationError(message=error when encoding the response, cta=Try again), ERR_GINV_606=GetInvitationError(message=the invited member is not the signed member, cta=Sign Out), ERR_GINV_607=GetInvitationError(message=error when encoding the response, cta=Try again), ERR_GINV_608=GetInvitationError(message=error when encoding the response, cta=Try again)} 2023-05-26 06:01:42.516 2352-2352 ErrorEncoded com. D COntainsKey : false 2023-05-26 06:01:42.516 2352-2352 ErrorEncoded com. D null
疑问
- 为什么containsKey返回false?
- 为什么getInvitationErrors[errorCode]返回null?
问题原因及解决方案
核心原因
最可能的情况是传入的errorCode包含不可见字符(比如首尾空格、换行符、制表符,或者其他控制字符)。虽然日志打印出来看起来和Map里的key完全一致,但这些不可见字符不会在日志中显示,导致字符串实际内容不同、哈希值不匹配,Map自然找不到对应条目。
另外也需要排查是否存在Map实例不匹配的情况:比如getInvitationErrors被重复定义、或者在运行时被重新赋值,导致你实际使用的Map和代码里定义的不是同一个。
解决方案
清理输入字符串
对传入的errorCode做预处理,去掉首尾空白和不可见字符:val cleanedErrorCode = errorCode.trim() // 先去掉首尾空格、换行等 .replace(Regex("\\p{C}"), "") // 过滤所有控制字符 // 用清理后的字符串去查找 val exists = getInvitationErrors.containsKey(cleanedErrorCode) val giError = getInvitationErrors[cleanedErrorCode]调试字符差异
临时添加日志,对比输入字符串和预期key的每个字符细节:val expectedKey = "ERR_GINV_601" Log.d("Debug", "输入码长度: ${errorCode.length} | 预期码长度: ${expectedKey.length}") // 打印输入码的每个字符及ASCII码 errorCode.forEachIndexed { idx, c -> Log.d("Debug", "输入字符[$idx]: '$c' (ASCII: ${c.code})") } // 打印预期key的每个字符及ASCII码 expectedKey.forEachIndexed { idx, c -> Log.d("Debug", "预期字符[$idx]: '$c' (ASCII: ${c.code})") }通过对比长度和每个字符的ASCII码,就能快速发现是否有隐藏字符。
验证Map实例一致性
打印Map的哈希值,确认使用的是你定义的那个实例:Log.d("Debug", "当前Map哈希值: ${getInvitationErrors.hashCode()}") // 可以在Map定义的地方也打印一次哈希值,对比是否一致
内容的提问来源于stack exchange,提问作者Mael Fosso
相关产品推荐
相关产品推荐

