Kotlin实现HashMap扩容后测试失败,求排查resize函数问题
扩容后HashMap测试失败的resize函数问题排查
你的Kotlin HashMap实现在触发扩容后测试失败,核心问题集中在元素转移逻辑、计数同步以及配套函数的一致性上,以下是具体错误分析和修复方案:
1. added变量未同步实际元素数量
当原Map存在remove操作或重复put同一key时,added的数值会与实际非空元素数量不符。resize时你遍历的是map.filterNotNull()(真实存在的元素),但added仍保留原数值,这会导致后续扩容判断逻辑错误,甚至出现元素数量统计失效的情况。
修复方案:
在resize末尾同步added为新Map的实际元素数:
fun resize() { val newMap = arrayOfNulls<Entry>(map.size * 2) var newAddedCount = 0 for (entry in map.filterNotNull()) { val index = hash(entry.key, newMap) val targetIndex = probe(index, entry.key, newMap) newMap[targetIndex] = Entry(entry.key, entry.value) newAddedCount++ } map = newMap added = newAddedCount // 同步真实元素数量 }
2. put函数覆盖已有key时错误递增added
当前put逻辑中,即使覆盖已存在的key,仍会执行added++,导致added远大于实际元素数,提前触发扩容,甚至在resize后出现计数混乱。
修复方案:
仅当新增元素时才递增added:
fun put(key: Int, value: Int) { if (added.toDouble() / map.size >= LOAD_FACTOR) resize() val index = hash(key, map) val targetIndex = probe(index, key, map) if (map[targetIndex] == null) { added++ } map[targetIndex] = Entry(key, value) }
3. 哈希函数未处理负数key
Kotlin中负数取模结果为负数(如-1 % 1000 = -1),会导致数组越界异常。虽然你的测试用例可能使用正整数key,但这是潜在的致命bug。
修复方案:
fun hash(key: Int, m: Array<Entry?>) = (key % m.size + m.size) % m.size
4. (可选)统一探测逻辑的严谨性
当前probe函数逻辑与get函数对齐,但可以优化写法,避免冗余的取模操作:
fun probe(index: Int, key: Int, m: Array<Entry?>): Int { val size = m.size var localIndex = index % size while (true) { val currentEntry = m[localIndex] if (currentEntry == null || currentEntry.key == key) { return localIndex } localIndex = (localIndex + 1) % size } }
修复后效果
以上修改解决了扩容过程中元素计数错误、哈希越界、重复key计数异常等问题,确保resize后所有元素能被正确转移,get/put/remove操作逻辑一致,测试用例在触发扩容后即可正常通过。
内容的提问来源于stack exchange,提问作者Dari V
相关产品推荐
相关产品推荐

