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

为什么使用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 09:33:12