为何HashMap调用toSortedMap后会少一个条目?
问题分析与解决:toSortedMap后丢失条目
你遇到的这个问题,核心原因是自定义的Comparator违反了SortedMap的比较契约,导致两个优先级相同的条目被错误判定为"相同键",进而被覆盖了。
为什么会丢失条目?
Kotlin的toSortedMap底层依赖Java的TreeMap,而TreeMap对比较器有严格的契约要求:如果compare(a, b) == 0,则必须满足a.equals(b) == true(等价一致性)。
看你的日志最后一次比较:对应test:xxx和test:yyy的两个UUID,它们的priority都是1,所以你的比较器返回了0。但这两个UUID是完全不同的(a.equals(b)为false),这就破坏了TreeMap的契约。此时TreeMap会认为这两个键是同一个,后面插入的xxx就会覆盖掉之前的yyy,最终导致排序后的Map少了一个条目。
修复方案
修改Comparator,当priority相同时,通过UUID本身的自然排序来区分不同的键,保证即使优先级相同,不同的UUID也会被视为独立的键。同时修正null处理的逻辑,避免破坏比较的对称性:
val sortedUuidToConfigMap = uuidToConfigMap.toSortedMap<UUID, Config>(object: Comparator<UUID>{ override fun compare(o1: UUID?, o2: UUID?): Int { val config1 = uuidToConfigMap[o1] val config2 = uuidToConfigMap[o2] // 先处理null情况,用UUID自身的compareTo保证逻辑正确 if (o1 == null) return o2?.let { -1 } ?: 0 if (o2 == null) return 1 if (config1 == null || config2 == null) { return o1.compareTo(o2) } // 优先按priority升序排序 val priorityDiff = config1.priority - config2.priority if (priorityDiff != 0) { return priorityDiff } // priority相同时,按UUID排序,确保键的唯一性 return o1.compareTo(o2) } })
修复后效果
修改后,排序后的Map会保留全部4个条目:两个priority=1的条目都会存在,排序顺序是先按priority升序排列,priority相同的条目则按UUID的自然顺序排列。
内容的提问来源于stack exchange,提问作者lannyf
相关产品推荐
相关产品推荐

