如何在 Java 中迭代 HashMap 值时替换它们

Posted

技术标签:

【中文标题】如何在 Java 中迭代 HashMap 值时替换它们【英文标题】:How to replace HashMap Values while iterating over them in Java 【发布时间】:2012-06-15 03:26:03 【问题描述】:

我正在使用 Runnable 每秒自动从玩家的冷却时间中减去 20,但我不知道如何在迭代时替换值的值。如何让它更新每个键的值?

public class CoolDownTimer implements Runnable 
    @Override
    public void run() 
        for (Long l : playerCooldowns.values()) 
            l = l - 20;
            playerCooldowns.put(Key???, l);
        
    


【问题讨论】:

【参考方案1】:

使用 Java 8:

map.replaceAll((k, v) -> v - 20);

使用 Java 7 或更早版本:

您可以遍历条目并更新值,如下所示:

for (Map.Entry<Key, Long> entry : playerCooldowns.entrySet()) 
    entry.setValue(entry.getValue() - 20);

【讨论】:

我不敢相信我没有想到这一点。谢谢。 实际上该模式有一个 FindBugs-Warning:低效使用 keySet 迭代器而不是 entrySet 迭代器 即使在大多数情况下并不重要,性能方面,在某些情况下,它可以产生巨大的影响。此外,我什至认为这两种情况下的代码都是清晰易读的。为什么要使用和发布一个明显有一些缺点而没有任何优点的模式? (即使缺点可以说很小) @aioobe:我可以想象这对不同的地图实现有不同的影响,当然,但是有没有一种形式的迭代比后者更有效?因此 FindBugs-Warning 会是误报吗?但你是对的,我们不必在这里讨论。我猜你的回答还可以。 您能解释一下为什么会这样吗?我记得,在使用 for each 循环对其进行迭代时,不允许更改集合的元素。 您不得进行结构更改,例如添加或删除元素。【参考方案2】:

好吧,你不能通过迭代 Map 中的值集来做到这一点(就像你现在正在做的那样),因为如果你这样做,那么你就没有对键的引用,如果你没有引用键,则无法更新映射中的条目,因为您无法找出与刚刚更新的值相关联的键。

在使用地图时,您有两个类似的更新选项,遍历Map 中的每个Map.Entry&lt;K,V&gt;,或者您可以遍历密钥SetMap 上有一些方法可以做这两件事。就个人而言,我会遍历每个Map.Entry&lt;K,V&gt;

for (Map.Entry<String, Long> entry : playerCooldowns.entrySet()) 
    entry.setValue(entry.getValue() - 20);

【讨论】:

【参考方案3】:

为什么不迭代 Map.Entry 对象?每个Entry 都会为您提供键和值,您无需在Map 上执行额外的get() 即可获得值。

【讨论】:

以上是关于如何在 Java 中迭代 HashMap 值时替换它们的主要内容,如果未能解决你的问题,请参考以下文章

java - 如何将Java hashMap内容的全部放在另一个上,但不替换现有的键和值?

HashMap遍历

在 Java(或 Scala)中迭代 HashMap 的 HashMap

在Java中迭代HashMap

如何在迭代时从 HashMap 中删除键? [复制]

无法使用 HashMap 替换方法:调用需要 api 级别 24(当前最小值为 22):java.util.HashMap#replace