我想从Map获取随机密钥及其各自的值。这个想法是随机生成器会选择一个键并显示该值。棘手的部分是键和值都是字符串,例如myMap.put("Geddy", "Lee")
。
答案 0 :(得分:48)
HashMap<String, String> x;
Random random = new Random();
List<String> keys = new ArrayList<String>(x.keySet());
String randomKey = keys.get( random.nextInt(keys.size()) );
String value = x.get(randomKey);
答案 1 :(得分:4)
这个问题应该对您Is there a way to get the value of a HashMap randomly in Java?提供帮助,而且Picking a random element from a set也应该HashMap
,HashSet
支持O(n)
。它可以是O(n)
时间和恒定空间,也可以是{{1}}额外空间和恒定时间。
答案 2 :(得分:3)
如果您不介意浪费的空间,一种方法是分别保留List
中所有密钥的Map
。为获得最佳性能,您需要具有良好随机访问性能的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)操作以从列表中删除键。
如果空间是一个很大的问题,但性能不是很好,你也可以在地图的入口集(Iterator
)上获得Map.entrySet()
,并在返回之前跳过randIndex
条目一个你想要的。但这将是一个O(N)操作,它有点击败了地图的整个点。
最后,您可以获取条目集toArray()
并随机索引。这更简单,但效率更低。
答案 3 :(得分:2)
如果你的键是整数或类似的东西,你可以使用TreeMap来做到这一点。
TreeMap<Integer, Integer> treeMap = new TreeMap<>();
int key = RandomUtils.ranInt(treeMap.lastKey());
int value = treeMap.ceilingKey(key);
答案 4 :(得分:1)
我会将Map复制到一个数组中并随机选择你想要的条目。这样就无需从密钥中查找值。
Map<String, String> x = new HashMap<String, String>();
Map.Entry<String,String>[] entries = x.entrySet().toArray(new Map.Entry[0]);
Random rand = new Random();
// call repeatedly
Map.Entry<String, String> keyValue = entries[rand.nextInt(entries.length)];
如果您想避免重复,可以随机化条目的顺序
Map<String, String> x = new HashMap<String, String>();
List<Map.Entry<String,String>> entries = new ArrayList<Map.Entry<String, String>> (x.entrySet());
Collections.shuffle(entries);
for (Map.Entry<String, String> entry : entries) {
System.out.println(entry);
}
答案 5 :(得分:1)
使用reservoir sampling选择随机键列表,然后将它们插入地图(以及源地图中的相应值)。
这样您就不需要将整个keySet
复制到数组中,只需复制选定的键。
public static <K, V>Map<K, V> sampleFromMap(Map<? extends K, ? extends V> source, int n, Random rnd) {
List<K> chosenKeys = new ArrayList<K>();
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<K, V> result = new HashMap<K, V>();
for (K k: chosenKeys) {
result.put(k, source.get(k));
}
return Collections.unmodifiableMap(result);
}
答案 6 :(得分:0)
toolbox.router.get('/(.)', toolbox.fastest);
toolbox.router.post('/(.)', toolbox.fastest);
toolbox.router.get('/(.)', toolbox.fastest, {origin: 'https://example.cloudfront.net'})
toolbox.router.get('/(.)', toolbox.fastest, {origin: 'https://example.in'})
答案 7 :(得分:-1)
自从玩过java以来已经有一段时间了,但是keySet()没有给你一个可以使用数字索引选择的列表吗?我想你可以选择一个随机数并从myMap的keySet中选择,然后从myMap中选择相应的值。现在无法测试,但它似乎尽可能地打击我!