3
If you don't mind the wasted space, one approach would be to separately keep a List
of all keys that are in the Map
. For best performance, you'll want a List
that has good random-access performance (like an ArrayList
). Then, just get a random number between 0 (inclusive) and list.size()
(exclusive), pull out the key at that index, and look that key up.
如果您不介意浪费的空间,一种方法是单独保留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);
This approach also means that adding a key-value pair is a good deal cheaper than removing one. To add the key-value pair, you would test to see if the key is already in the map (if your values can be null, you'll have to separately call map.containsKey
; if not, you can just add the key-value pair and see if the "old value" it returns is null)
. If the key is already in the map, the list is unchanged, but if not, you add the key to the list (an O(1) operation for most lists). Removing a key-value pair, though, involves an O(N) operation to remove the key from the list.
这种方法也意味着添加键值对比删除键值便宜。要添加键值对,您将测试键是否已经在地图中(如果您的值可以为null,则必须单独调用map.containsKey;如果不是,您只需添加键 - 值对并查看它返回的“旧值”是否为空)。如果密钥已经在映射中,则列表将保持不变,但如果不是,则将密钥添加到列表中(对于大多数列表,为O(1)操作)。但是,删除键值对涉及O(N)操作以从列表中删除键。
If space is a big concern, but performance is less so, you could also get an Iterator
over the map's entry set (Map.entrySet()
), and skip randIndex
entries before returning the one you want. But that would be an O(N) operation, which kinda defeats the whole point of a map.
如果空间是一个很大的问题,但性能不那么重要,你也可以在地图的入口集(Map.entrySet())上获得一个迭代器,并在返回你想要的那个之前跳过randIndex条目。但这将是一个O(N)操作,它有点击败了地图的整个点。
Finally, you can just get the entry set's toArray()
and randomly index into that. That's simpler, though less efficient.
最后,您可以获取条目集的toArray()并随机索引到该条目。这更简单,但效率更低。