从Java中的Map中选择随机键和值集

我想从Map获取随机密钥及其各自的值。 这个想法是随机生成器会选择一个键并显示该值。 棘手的部分是键和值都是字符串,例如myMap.put("Geddy", "Lee")

 HashMap x; Random random = new Random(); List keys = new ArrayList(x.keySet()); String randomKey = keys.get( random.nextInt(keys.size()) ); String value = x.get(randomKey); 

这个问题应该对你有所帮助有没有办法在Java中随机获取HashMap的值? 这个也从一个集中挑选一个随机元素,因为HashMap由一个HashSet支持。 它可以是O(n)时间和恒定空间,也可以是O(n)额外空间和恒定时间。

如果您不介意浪费的空间,一种方法是单独保留Map中所有键的List 。 为了获得最佳性能,您需要一个具有良好随机访问性能的List (如ArrayList )。 然后,只需获得0(含)和list.size() (不包括)之间的随机数,拉出该索引处的键,然后查看该键。

 Random rand = something int randIndex = rand.nextInt(list.size()); K key = list.get(randIndex); V value = map.get(key); 

这种方法也意味着添加键值对比删除键值便宜。 要添加键值对,您将测试键是否已经在地图中(如果您的值可以为null,则必须单独调用map.containsKey ;如果不是,您只需添加键 -值对并查看它返回的“旧值”是否为null) 。 如果密钥已经在映射中,则列表将保持不变,但如果不是,则将密钥添加到列表中(对于大多数列表,为O(1)操作)。 但是,删除键值对涉及O(N)操作以从列表中删除键。

如果空间是一个很大的问题,但性能不那么重要,你也可以在地图的入口集( Map.entrySet() )上获得一个Iterator ,并在返回你想要的randIndex之前跳过randIndex条目。 但这将是一个O(N)操作,它有点击败了地图的整个点。

最后,您可以获取条目集的toArray()并随机索引到该条目。 这更简单,但效率更低。

如果你的键是整数或类似的东西,你可以使用TreeMap来做到这一点。

 TreeMap treeMap = new TreeMap<>(); int key = RandomUtils.ranInt(treeMap.lastKey()); int value = treeMap.ceilingKey(key); 

我会将Map复制到一个数组中并随机选择你想要的条目。 这样就无需从密钥中查找值。

 Map x = new HashMap(); Map.Entry[] entries = x.entrySet().toArray(new Map.Entry[0]); Random rand = new Random(); // call repeatedly Map.Entry keyValue = entries[rand.nextInt(entries.length)]; 

如果要避免重复,可以随机化条目的顺序

 Map x = new HashMap(); List> entries = new ArrayList> (x.entrySet()); Collections.shuffle(entries); for (Map.Entry entry : entries) { System.out.println(entry); } 

使用油藏采样选择随机键列表,然后将它们插入地图(以及源地图中的相应值)。

这样您就不需要将整个keySet复制到一个数组中,只需复制选定的键。

 public static Map sampleFromMap(Map source, int n, Random rnd) { List chosenKeys = new ArrayList(); int count = 0; for (K k: source.keySet()) { if (count++ < n) { chosenKeys.add(k); if (count == n) { Collections.shuffle(chosenKeys, rnd); } } else { int pos = rnd.nextInt(count); if (pos < n) { chosenKeys.set(pos, k); } } } Map result = new HashMap(); for (K k: chosenKeys) { result.put(k, source.get(k)); } return Collections.unmodifiableMap(result); } 
 In some cases you might want to preserve an order you put the elements in the Set, In such scenario you can use, This Set alldocsId = new HashSet<>(); for (int i=0;i alldocIDlst = new ArrayList<>(); Iterator it = alldocsId.iterator(); while (it.hasNext()) { alldocIDlst.add(Integer.valueOf(it.next().toString())); } 

自从玩过java以来​​已经有一段时间了,但是keySet()没有给你一个可以使用数字索引选择的列表吗? 我想你可以选择一个随机数并从myMap的keySet中选择,然后从myMap中选择相应的值。 现在无法测试,但它似乎尽可能地打击我!