上一题下一题

线上缓存使用 HashMap 保存用户对象,用户修改参与 hashCode 的字段后出现 containsKey 失败和重复键,如何复现问题、修复键设计并制定数据迁移方案?

基础版
来源:alibaba中级工程师集合唯一性语义HashMap键可变性哈希键不可变设计缓存数据迁移
草稿该题目为草稿状态,前台公开题库中不可见。
答案解析

线上问题的根因通常是:对象作为 HashMap 的键时,hashCode 和 equals 依赖了可变字段。插入时,键被放在旧哈希值对应的桶里;字段修改后,查询会按新哈希值查找,可能找不到原条目。再用这个对象执行 put 时,Map 可能把它当成另一个键插入,于是出现逻辑上的重复键。即使对象仍在 Map 中,size 也可能增长,而按修改后的键查询不到旧值。

复现时定义一个 UserKey,让 id 参与 hashCode 和 equals,先执行 map.put(key, value),再修改 key.id,然后执行 map.containsKey(key) 和 map.put(key, anotherValue)。为了让现象稳定,可以选取哈希桶位置会变化的字段值,并验证 Map 的遍历结果、size 和查询结果。需要注意,HashMap 对可变键的行为不保证能通过再次查询或删除修复,具体表现也会受哈希分布影响。

修复上,我会把键改成不可变、稳定且唯一的标识,例如用户 ID:Map<UserId, User 。如果业

登录后查看完整内容