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

Java中如何从HashMap移除k个值最大的元素?

问题原因与解决方案

你遇到的ConcurrentModificationException是因为HashMap的迭代器是快速失败的:当你用增强for循环遍历entrySet时,底层依赖HashMap内置的迭代器工作,这时候直接调用hMap.remove(key)修改Map结构,迭代器会立刻检测到这个非法修改并抛出异常——它不允许遍历和直接修改Map结构同时进行(除非用迭代器自身的修改方法)。

另外你代码里还有个笔误:定义的Map变量是myMap,删除时却用了hMap,需要统一。

下面给出几种可行的解决方法:

方法1:使用迭代器的remove()方法

把增强for循环换成显式的Iterator遍历,找到目标元素时调用迭代器的remove()方法,这是迭代器允许的合法修改方式,不会触发异常:

int k = 3;
HashMap<Integer, Integer> myMap = new HashMap<>(Map.of(1,3,2,2,3,6,4,8,5,2,6,1));

for (int i = 0; i < k; i++) {
    Integer maxVal = Collections.max(myMap.values());
    Iterator<Map.Entry<Integer, Integer>> iterator = myMap.entrySet().iterator();
    while (iterator.hasNext()) {
        Map.Entry<Integer, Integer> entry = iterator.next();
        if (entry.getValue().equals(maxVal)) {
            iterator.remove(); // 用迭代器的remove方法,避免并发修改异常
            break; // 找到一个最大值就退出,确保每次循环只删一个元素
        }
    }
}

System.out.println(myMap); // 输出 {2=2, 5=2, 6=1}

方法2:先收集待删除的键,再批量删除

先通过Stream筛选出前k个最大值对应的键,再批量删除,这种方式更高效,尤其适合元素较多的场景:

int k = 3;
HashMap<Integer, Integer> myMap = new HashMap<>(Map.of(1,3,2,2,3,6,4,8,5,2,6,1));

// 按值从大到小排序,取前k个键
List<Integer> keysToRemove = myMap.entrySet()
        .stream()
        .sorted(Map.Entry.comparingByValue(Comparator.reverseOrder()))
        .limit(k)
        .map(Map.Entry::getKey)
        .toList();

keysToRemove.forEach(myMap::remove);

System.out.println(myMap); // 输出 {2=2, 5=2, 6=1}

方法3:避开迭代时修改Map的逻辑

如果不想用迭代器或Stream,可以先找到当前最大值对应的键,再单独删除(不在遍历entrySet的过程中修改Map):

int k = 3;
HashMap<Integer, Integer> myMap = new HashMap<>(Map.of(1,3,2,2,3,6,4,8,5,2,6,1));

for (int i = 0; i < k; i++) {
    Integer maxVal = Collections.max(myMap.values());
    Integer keyToRemove = null;
    // 先找到要删除的键
    for (Map.Entry<Integer, Integer> entry : myMap.entrySet()) {
        if (entry.getValue().equals(maxVal)) {
            keyToRemove = entry.getKey();
            break;
        }
    }
    // 单独删除,不在遍历迭代器时修改
    if (keyToRemove != null) {
        myMap.remove(keyToRemove);
    }
}

System.out.println(myMap); // 输出 {2=2, 5=2, 6=1}

注意细节

  • 比较Integer值时尽量用equals()而非==,因为Integer有缓存池,超过范围的数值用==会比较对象地址,导致判断错误。

内容的提问来源于stack exchange,提问作者blindflip

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 20:45:32