如何在 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<K,V>
,或者您可以遍历密钥Set
。 Map
上有一些方法可以做这两件事。就个人而言,我会遍历每个Map.Entry<K,V>
。
for (Map.Entry<String, Long> entry : playerCooldowns.entrySet())
entry.setValue(entry.getValue() - 20);
【讨论】:
【参考方案3】:为什么不迭代 Map.Entry 对象?每个Entry
都会为您提供键和值,您无需在Map
上执行额外的get()
即可获得值。
【讨论】:
以上是关于如何在 Java 中迭代 HashMap 值时替换它们的主要内容,如果未能解决你的问题,请参考以下文章
java - 如何将Java hashMap内容的全部放在另一个上,但不替换现有的键和值?
在 Java(或 Scala)中迭代 HashMap 的 HashMap
无法使用 HashMap 替换方法:调用需要 api 级别 24(当前最小值为 22):java.util.HashMap#replace