【问题标题】:Java HashMap - How to simultaneously get and then remove a random entry from a HashMap?Java HashMap - 如何同时获取然后从 HashMap 中删除随机条目?
【发布时间】:2018-11-11 04:44:16
【问题描述】:

我想知道是否可以从 HashMap 中获取随机值,然后直接从 HashMap 中删除该键/值?我似乎找不到任何有效的方法,不同的数据结构会更适合吗?

编辑: 我应该更清楚,我生成一个随机数,然后检索与该随机数对应的值。我需要返回该值,然后从地图中删除该条目。

【问题讨论】:

  • 只需调用 remove(key) 即可删除带有该键的元素。
  • 随机条目是什么意思?随机条目将由谁选择?
  • 我应该更清楚,我生成一个随机数,然后检索与该随机数对应的值。我需要返回该值,然后从地图中删除该条目。
  • HashMap 上使用.keySet 方法获取所有现有密钥作为Set;在键集上使用.toArray 方法来获取键数组。生成一个介于零和密钥数组大小之间的随机数;在该索引处获取密钥k,在HashMap 上使用.remove(k)

标签: java dictionary hashmap


【解决方案1】:

也许Map#computeIfPresent 适合您的情况。来自其documentation

如果指定键的值存在且非空,则尝试在给定键及其当前映射值的情况下计算新映射。

如果重映射函数返回 null,则删除映射。

var map = new HashMap<Integer, String>();

map.put(1, "One");
map.put(2, "Two");
map.put(3, "Three");

map.computeIfPresent(2, (k, v) -> {
    // `v` is equal to "Two"
    return null; // Returning `null` removes the entry from the map.
});

System.out.println(map);

以上代码输出如下:

{1=One, 3=Three}

如果您要使用ConcurrentHashMap,那么这将是一个原子操作。

【讨论】:

  • computeIfPresent 返回新值,而不是旧值。
  • @KonstantinSvintsov 好的,这与这个答案有什么关系?
  • 我认为它没有回答这个问题。问题是如何从映射中获取值并使用单个(同步映射的原子?)操作删除该值,computeIfPresent 不会这样做。
【解决方案2】:

据我了解,问题是这样的:给定一个 HashMap 你想要

  1. Map中当前关联的键中随机选择一个键;
  2. 从映射中删除该随机选择的键的关联;和
  3. 返回直到最近才与该键关联的值

这是一个如何做到这一点的示例,以及一些小测试/演示例程:

public class Main
{
    private static <K, V> V removeRandomEntry(Map<K, V> map){
        Set<K> keySet = map.keySet();
        List<K> keyList = new ArrayList<>(keySet);
        K keyToRemove = keyList.get((int)(Math.random()*keyList.size()));
        return map.remove(keyToRemove);
    }

    public static void main(String[] args){
        Map<String, String> map = new HashMap<>();
        for(int i = 0; i < 100; ++i)
            map.put("Key" + i, "Value"+i);
        int pass = 0;
        while (!map.isEmpty())
            System.out.println("Pass " + (++pass) + ": Removed: " + removeRandomEntry(map));
    }
}

【讨论】:

    【解决方案3】:

    我会这样做:

    Hashmap<Integer, Object> example;
    int randomNum = ThreadLocalRandom.current().nextInt(0, example.size());
    example.getValue() //do something
    example.remove(new Integer(randomNum));
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-03-30
      • 2015-05-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多