Is there a way to get the value of a HashMap randomly in Java?
-
1Why do you need this? If it's anything other than testing, you're using the wrong data structure. If it's for testing, then you probably don't want random data. – kdgregory May 30 '09 at 11:21
-
See my answer below -- the appropriate way to do this depends a little on your circumstances (notably how many random elements you need per change to the map). – Neil Coffey May 30 '09 at 13:08
-
1If you want something efficient, take a look at my answer in http://stackoverflow.com/questions/9919734/selecting-random-key-and-value-sets-from-a-map-in-java/20724193#20724193 Hashtables are in principle a great structure for accessing random elements. It's unfortunate that the Java api doesn't give us an easy way to do it. – Thomas Ahle Dec 21 '13 at 22:30
-
@kdgregory hi, I know it's an old thread, but I wonder why you're saying its the wrong data structure for random access? Thanks – MTA Feb 04 '15 at 13:41
-
2@RegUser - HashMaps are designed to be accessed by key rather than value. There are uses for bidirectional mappings, but you should choose a class designed for that purpose and not try force HashMap to do something that it wasn't designed to do. – kdgregory Feb 05 '15 at 19:34
14 Answers
This works:
Random generator = new Random();
Object[] values = myHashMap.values().toArray();
Object randomValue = values[generator.nextInt(values.length)];
If you want the random value to be a type other than an Object
simply add a cast to the last line. So if myHashMap
was declared as:
Map<Integer,String> myHashMap = new HashMap<Integer,String>();
The last line can be:
String randomValue = (String) values[generator.nextInt(value.length)];
The below doesn't work, Set.toArray()
always returns an array of Object
s, which can't be coerced into an array of Map.Entry
.
Random generator = new Random();
Map.Entry[] entries = myHashMap.entrySet().toArray();
randomValue = entries[generator.nextInt(entries.length)].getValue();

- 5,622
- 6
- 25
- 39

- 13,090
- 2
- 35
- 36
-
1when executing your code Tom I get the exception "incompatible types-found java.util.object[] but expected java.util.entry[]" – Varuna May 31 '09 at 01:49
-
How to do the necessary type casting?I have tried to Map, Map.Entry the message displayed is inconvertible types – Varuna May 31 '09 at 01:59
-
Hi Varuna, you're quite correct, that code was broken! I've added some code to my answer that does work. – Tom Jefferys May 31 '09 at 10:52
-
The post below this by coobird is also correct and it works But I choose this as the correct solution because this more simple – Varuna Jun 03 '09 at 19:14
-
If you want to use the first method, use the overloaded `toArray(T[] arr)` method, `Map.Entry
[] entries = s.entrySet().toArray(new Map.Entry[s.size()]);` (you should have a warning though because you cannot create a parametrized array) – Alexis C. Apr 25 '14 at 22:25 -
-
You may want to consider using [`toArray(T[])`](https://docs.oracle.com/javase/8/docs/api/java/util/List.html#toArray-T:A-) with a size 0 array to avoid a cast. – Just a student Aug 16 '18 at 07:20
-
2Hi, can you edit the answer so it doesn't contain not-working part? It's very confusing. – Line Nov 16 '18 at 08:09
Since the requirements only asks for a random value from the HashMap
, here's the approach:
- The
HashMap
has avalues
method which returns aCollection
of the values in the map. - The
Collection
is used to create aList
. - The
size
method is used to find the size of theList
, which is used by theRandom.nextInt
method to get a random index of theList
. - Finally, the value is retrieved from the
List
get
method with the random index.
Implementation:
HashMap<String, Integer> map = new HashMap<String, Integer>();
map.put("Hello", 10);
map.put("Answer", 42);
List<Integer> valuesList = new ArrayList<Integer>(map.values());
int randomIndex = new Random().nextInt(valuesList.size());
Integer randomValue = valuesList.get(randomIndex);
The nice part about this approach is that all the methods are generic -- there is no need for typecasting.

- 159,216
- 35
- 211
- 226
-
1Dear coobird your code is correct is and it works But I choose the above by Tom since it appears to me as more simple!!!!! Thanks for your help – Varuna Jun 03 '09 at 19:15
Should you need to draw futher values from the map without repeating any elements you can put the map into a List and then shuffle it.
List<Object> valuesList = new ArrayList<Object>(map.values());
Collections.shuffle( valuesList );
for ( Object obj : valuesList ) {
System.out.println( obj );
}

- 4,490
- 2
- 29
- 32
-
+1 for Collections.shuffle(); I hadn't seen that before. Cool; thanks! – Carl Manaster May 30 '09 at 20:35
Generate a random number between 0 and the number of keys in your HashMap
. Get the key at the random number. Get the value from that key.
Pseudocode:
int n = random(map.keys().length());
String key = map.keys().at(n);
Object value = map.at(key);
If it's hard to implement this in Java, then you could create and array from this code using the toArray()
function in Set
.
Object[] values = map.values().toArray(new Object[map.size()]);
Object random_value = values[random(values.length)];
I'm not really sure how to do the random number.

- 5,084
- 1
- 23
- 28
-
3except that's untranslatable to Java, since the keys of a Map are a Set, and Sets don't have any sense of position – kdgregory May 30 '09 at 11:19
-
Removing the downvote because you looked up the correct methods (although I still think the OP needs to rethink the problem). Take a look at java.lang.Random for the random number. – kdgregory May 30 '09 at 11:30
Converting it to an array and then getting the value is too slow when its in the hot path.
so get the set (either the key or keyvalue set) and do something like:
public class SetUtility {
public static<Type> Type getRandomElementFromSet(final Set<Type> set, Random random) {
final int index = random.nextInt(set.size());
Iterator<Type> iterator = set.iterator();
for( int i = 0; i < index-1; i++ ) {
iterator.next();
}
return iterator.next();
}

- 2,975
- 1
- 24
- 32
If you are using Java 8, findAny
function in a pretty solution:
MyEntityClass myRandomlyPickedObject = myHashMap.values().stream().findAny();

- 651
- 6
- 10
-
This is bad practice as it's replacing a HashMap read O(1) by a linear iteration O(n). Acceptable for small Maps, but you're doomed if size grows. In short: Don't do convenience coding if you're saving one or two lines. Never. – supernova Jul 25 '21 at 10:09
-
All the other high voted answers are linear, which iterate over all the elements. Here, at least, not all elements must be iterated over. – AlikElzin-kilaka Dec 15 '21 at 14:55
-
Ran some tests and it seems that `findAny()` doesn't always randomize. – AlikElzin-kilaka Dec 15 '21 at 15:03
It seems that all other high voted answers iterate over all the elements. Here, at least, not all elements must be iterated over:
Random generator = new Random();
return myHashMap.values().stream()
.skip(random.nextInt(myHashMap.size()))
.findFirst().get();

- 34,335
- 35
- 194
- 277
A good answer depends slightly on the circumstances, in particular how often you need to get a random key for a given map (N.B. the technique is essentially the same whether you take key or value).
- If you need various random keys from a given map, without the map changing in between getting the random keys, then use the random sampling method as you iterate through the key set. Effectively what you do is iterate over the set returned by keySet(), and on each item calculate the probability of wanting to take that key, given how many you will need overall and the number you've taken so far. Then generate a random number and see if that number is lower than the probability. (N.B. This method will always work, even if you only need 1 key; it's just not necessarily the most efficient way in that case.)
- The keys in a HashMap are effectively in pseudo-random order already. In an extreme case where you will only ever need one random key for a given possible map, you could even just pull out the first element of the keySet().
- In other cases (where you either need multiple possible random keys for a given possible map, or the map will change between you taking random keys), you essentially have to create or maintain an array/list of the keys from which you select a random key.

- 21,615
- 7
- 62
- 83
-
1
-
ah sorry missed that -- the same essentially applies, though whether you take the key or value. – Neil Coffey May 30 '09 at 17:02
Usually you do not really want a random value but rather just any value, and then it's nice doing this:
Object selectedObj = null;
for (Object obj : map.values()) {
selectedObj = obj;
break;
}

- 1,141
- 1
- 9
- 18
I wrote a utility to retrieve a random entry, key, or value from a map, entry set, or iterator.
Since you cannot and should not be able to figure out the size of an iterator (Guava can do this) you will have to overload the randEntry()
method to accept a size which should be the length of the entries.
package util;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
public class MapUtils {
public static void main(String[] args) {
Map<String, Integer> map = new HashMap<String, Integer>() {
private static final long serialVersionUID = 1L;
{
put("Foo", 1);
put("Bar", 2);
put("Baz", 3);
}
};
System.out.println(randEntryValue(map));
}
static <K, V> Entry<K, V> randEntry(Iterator<Entry<K, V>> it, int count) {
int index = (int) (Math.random() * count);
while (index > 0 && it.hasNext()) {
it.next();
index--;
}
return it.next();
}
static <K, V> Entry<K, V> randEntry(Set<Entry<K, V>> entries) {
return randEntry(entries.iterator(), entries.size());
}
static <K, V> Entry<K, V> randEntry(Map<K, V> map) {
return randEntry(map.entrySet());
}
static <K, V> K randEntryKey(Map<K, V> map) {
return randEntry(map).getKey();
}
static <K, V> V randEntryValue(Map<K, V> map) {
return randEntry(map).getValue();
}
}

- 42,981
- 12
- 84
- 132
If you are fine with O(n)
time complexity you can use methods like values()
or values().toArray()
but if you look for a constant O(1)
getRandom()
operation one great alternative is to use a custom data structure. ArrayList
and HashMap
can be combined to attain O(1)
time for insert()
, remove()
and getRandom()
. Here is an example implementation:
class RandomizedSet {
List<Integer> nums = new ArrayList<>();
Map<Integer, Integer> valToIdx = new HashMap<>();
Random rand = new Random();
public RandomizedSet() { }
/**
* Inserts a value to the set. Returns true if the set did not already contain
* the specified element.
*/
public boolean insert(int val) {
if (!valToIdx.containsKey(val)) {
valToIdx.put(val, nums.size());
nums.add(val);
return true;
}
return false;
}
/**
* Removes a value from the set. Returns true if the set contained the specified
* element.
*/
public boolean remove(int val) {
if (valToIdx.containsKey(val)) {
int idx = valToIdx.get(val);
int lastVal = nums.get(nums.size() - 1);
nums.set(idx, lastVal);
valToIdx.put(lastVal, idx);
nums.remove(nums.size() - 1);
valToIdx.remove(val);
return true;
}
return false;
}
/** Get a random element from the set. */
public int getRandom() {
return nums.get(rand.nextInt(nums.size()));
}
}
The idea comes from this problem from leetcode.com.

- 992
- 11
- 26
Here is an example how to use the arrays approach described by Peter Stuifzand, also through the values()
-method:
// Populate the map
// ...
Object[] keys = map.keySet().toArray();
Object[] values = map.values().toArray();
Random rand = new Random();
// Get random key (and value, as an example)
String randKey = keys[ rand.nextInt(keys.length) ];
String randValue = values[ rand.nextInt(values.length) ];
// Use the random key
System.out.println( map.get(randKey) );

- 975
- 1
- 9
- 13
-
1This returns a random key and value, but, not a pair that is a key-value mapping in the map! – Sean Owen May 30 '09 at 12:12
-
Yes, but the example was to show how to randomize keys and values (see OPs comment from the post above this). :) I will clarify the example, though. – MH114 May 30 '09 at 12:28
-
i really don't know why you want to do this... but if it helps, i've created a RandomMap that automatically randomizes the values when you call values(), then the following runnable demo application might do the job...
package random;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
public class Main {
public static void main(String[] args) {
Map hashMap = makeHashMap();
// you can make any Map random by making them a RandomMap
// better if you can just create the Map as a RandomMap instead of HashMap
Map randomMap = new RandomMap(hashMap);
// just call values() and iterate through them, they will be random
Iterator iter = randomMap.values().iterator();
while (iter.hasNext()) {
String value = (String) iter.next();
System.out.println(value);
}
}
private static Map makeHashMap() {
Map retVal;
// HashMap is not ordered, and not exactly random (read the javadocs)
retVal = new HashMap();
// TreeMap sorts your map based on Comparable of keys
retVal = new TreeMap();
// RandomMap - a map that returns stuff randomly
// use this, don't have to create RandomMap after function returns
// retVal = new HashMap();
for (int i = 0; i < 20; i++) {
retVal.put("key" + i, "value" + i);
}
return retVal;
}
}
/**
* An implementation of Map that shuffles the Collection returned by values().
* Similar approach can be applied to its entrySet() and keySet() methods.
*/
class RandomMap extends HashMap {
public RandomMap() {
super();
}
public RandomMap(Map map) {
super(map);
}
/**
* Randomize the values on every call to values()
*
* @return randomized Collection
*/
@Override
public Collection values() {
List randomList = new ArrayList(super.values());
Collections.shuffle(randomList);
return randomList;
}
}

- 10,894
- 8
- 44
- 63
It depends on what your key is - the nature of a hashmap doesn't allow for this to happen easily.
The way I can think of off the top of my head is to select a random number between 1 and the size of the hashmap, and then start iterating over it, maintaining a count as you go - when count is equal to that random number you chose, that is your random element.

- 36,057
- 7
- 42
- 54
-
Kazer The key and the value I in my map are both of type String, it is in this situation that I have faced this problem.There is a value() method which returns a collections view according to the documentation, is it possible through this to take only the HashMap values(not keys) and get a random value? – Varuna May 30 '09 at 11:18
-
Of course, though this then raises the question of why you're using a hash map in the first place... – Neil Coffey May 30 '09 at 12:56