为什么使用Map的keySet时replace方法无法正常工作?
问题原因与修复方案
问题根源
你这段代码的核心问题是修改了HashMap的键对象(HashSet)的内容,导致该键的hashCode发生变化,进而让tickets.replace(oneTicket, result)无法找到对应的键,所以值根本没被更新。
HashMap的工作依赖键对象的hashCode()和equals()方法,当你调用oneTicket.retainAll(winningNumbers)时,直接修改了作为键的HashSet的元素,它的hashCode会重新计算。而这个键在HashMap中存储的位置是基于修改前的hashCode,此时用修改后的键去调用replace,HashMap找不到对应的条目,自然不会更新值。同时,这种修改键对象的操作还会破坏HashMap的内部结构,可能导致后续无法正确访问这些键。
修复方案
不要直接修改作为键的Set,而是创建临时集合计算交集大小,再用原键更新值。修改后的代码如下:
迭代器版本
public void ticketCheck() { // tickets and winningNumbers will come as parameters, now it is only an example: Map<Set<Integer>,Integer> tickets = new HashMap<Set<Integer>,Integer>(){ { put(new HashSet<Integer>(Set.of(5,21,25,32,38,40)) ,0); put(new HashSet<Integer>(Set.of(8,11,17,29,32,45)) ,0); }; }; Set<Integer> winningNumbers = new HashSet<Integer>(Set.of(11,20,32,33,36,45)); Iterator<Set<Integer>> itr = tickets.keySet().iterator(); while (itr.hasNext()) { Set<Integer> oneTicket = itr.next(); // 创建临时集合计算交集,不修改原键 Set<Integer> intersection = new HashSet<>(oneTicket); intersection.retainAll(winningNumbers); int result = intersection.size(); // 用未修改的原键去更新值 tickets.replace(oneTicket, result); } for (Map.Entry<Set<Integer>, Integer> item : tickets.entrySet()) { System.out.println(item.getKey() + " hits: "+item.getValue()); } }
更简洁的Entry遍历版本
public void ticketCheck() { Map<Set<Integer>,Integer> tickets = new HashMap<Set<Integer>,Integer>(){ { put(new HashSet<Integer>(Set.of(5,21,25,32,38,40)) ,0); put(new HashSet<Integer>(Set.of(8,11,17,29,32,45)) ,0); }; }; Set<Integer> winningNumbers = new HashSet<Integer>(Set.of(11,20,32,33,36,45)); for (Map.Entry<Set<Integer>, Integer> entry : tickets.entrySet()) { Set<Integer> oneTicket = entry.getKey(); Set<Integer> intersection = new HashSet<>(oneTicket); intersection.retainAll(winningNumbers); entry.setValue(intersection.size()); } for (Map.Entry<Set<Integer>, Integer> item : tickets.entrySet()) { System.out.println(item.getKey() + " hits: "+item.getValue()); } }
修改后执行,会得到期望输出:
[32] hits: 1
[32, 11, 45] hits: 3
内容的提问来源于stack exchange,提问作者bebo969
相关产品推荐
相关产品推荐

