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

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和代码里定义的不是同一个。

解决方案

  1. 清理输入字符串
    对传入的errorCode做预处理,去掉首尾空白和不可见字符:

    val cleanedErrorCode = errorCode.trim() // 先去掉首尾空格、换行等
        .replace(Regex("\\p{C}"), "") // 过滤所有控制字符
    // 用清理后的字符串去查找
    val exists = getInvitationErrors.containsKey(cleanedErrorCode)
    val giError = getInvitationErrors[cleanedErrorCode]
    
  2. 调试字符差异
    临时添加日志,对比输入字符串和预期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码,就能快速发现是否有隐藏字符。

  3. 验证Map实例一致性
    打印Map的哈希值,确认使用的是你定义的那个实例:

    Log.d("Debug", "当前Map哈希值: ${getInvitationErrors.hashCode()}")
    // 可以在Map定义的地方也打印一次哈希值,对比是否一致
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 23:12:55