【问题标题】:Short method to remove specific entries from hashmap从哈希图中删除特定条目的简短方法
【发布时间】:2015-04-30 18:32:03
【问题描述】:

我一直在寻找一种简短易读的方法来从哈希图中删除条目。 具体来说,这是我的方法:

Map<String, HashMap<String, Long>> kitcooldowns = new HashMap<String, HashMap<String, Long>>();


// METHOD TO REMOVE EXPIRED COOLDOWNS FROM HASHMAP

final long currentime = System.currentTimeMillis();
final HashMap<String, HashMap<String, Long>> tmp = new HashMap<String, HashMap<String,Long>>();
for (final Entry<String, HashMap<String, Long>> kits : kitcooldowns.entrySet()) {
    final HashMap<String, Long> newitems = new HashMap<String, Long>();
    for (final Entry<String, Long> item : kits.getValue().entrySet()) {
        if (item.getValue() + getCooldownTime(item.getKey()) > currentime) {
            newitems.put(item.getKey(), item.getValue());
        }
    }
    if (newitems.isEmpty() == false) tmp.put(kits.getKey(), newitems);
}

kitcooldowns = tmp;


private long getCooldownTime(final String type) {
    switch (type) {
    case "CooldownX":
        return 3600000;
    case "CooldownY":
        return 1800000;
    default:
        return 0L;
    }
}

为了简化,这是主要结构:

MAP<NAME OF PLAYER, MAP<TYPE OF COOLDOWN, TIME WHEN USED>>

如果特定的冷却时间已过期,则玩家将从哈希图中移除。 现在,这对我来说似乎是一个混乱的解决方案,我相信还有更好的解决方案。

编辑: 我的问题是,如果 Java 8 有一种高效且干净的方法(如迭代器),它为大多数长方法提供了大量新的单行解决方案。

【问题讨论】:

    标签: java hashmap


    【解决方案1】:

    无需创建单独的地图。如果您遍历地图的entrySet()values(),则可以使用Iterator#remove()

    for (Iterator<Entry<String, Long>> iter = kitcooldowns.entrySet().iterator(); iter.hasNext();) {
      Entry<String, Long> entry = iter.next();
      if (entry.getValue() + getCooldownTime(entry.getKey()) > currentime) {
        iter.remove();
      }
    }
    

    OP 想知道:

    Java 8 没有单行解决方案吗?

    当然,但是我强烈警告您不要仅仅因为可以就将所有内容都写成单行字。请记住,代码的存在是为了让未来的开发人员阅读,而不是尽可能简洁地编写。此外,使用Iterator#remove() 的代码将使用更少的内存,因为它不必复制地图。使用更少内存的代码最终也会变得更快,因为更少的内存使用会导致更少的 GC(这会消耗 CPU 时间)和更少的 CPU 缓存未命中。

    也就是说:

    kitcooldowns = kitcooldowns.entrySet().stream()
      .filter(entry -> entry.getValue() + getCooldownTime(entry.getKey()) <= currentime)
      .collect(Collectors.toMap(Entry::getKey, Entry::getValue));
    

    【讨论】:

    • Java 8 没有单行解决方案吗?提前致谢。
    • 当然,您可以使用流、过滤器等来做到这一点,但我认为这不会使代码变得更加简洁。为什么必须是 1-liner?
    • 查看我的编辑,尽管出于上述原因我真的不能宽恕它。
    【解决方案2】:

    您可以简单地使用这个 Java 单线:

        final long currentime = System.currentTimeMillis();
        kitcooldowns.entrySet().removeIf(entry -> entry.getValue().entrySet()
        .removeIf(entry2 -> entry2.getValue() + getCooldownTime(entry2.getKey()) 
        < currentime) && entry.getValue().isEmpty());
    

    【讨论】:

      猜你喜欢
      • 2010-09-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多