I've created a generic solution that utilizes the answer of Mike and SecureRandom, and includes explicit null and bounds checking, as well as a quick return for singleton collections (not much to choose there).
public static <T> T getRandomElement(Collection<T> collection) {
if (collection == null || collection.isEmpty()) {
throw new IllegalArgumentException("Collection should not be null or empty");
}
if (collection.size() == 1) {
return collection.iterator().next();
}
// it would be beneficial to make this a field when used a lot
final Random random = new SecureRandom();
final int randomIndex = random.nextInt(collection.size());
// optimization for list instances, use optimized indexing
if (collection instanceof List) {
final List<T> list = (List<T>) collection;
return list.get(randomIndex);
}
int seen = 0;
for (T e : collection) {
if (seen++ == randomIndex) {
return e;
}
}
throw new IllegalStateException("Collection size was altered during operation");
}
Now you can simply retrieve a String
and Integer
by first selecting a key value from the key set, taking the value and choosing a random integer from that.
String key = getRandomElement(aMap.keySet());
Integer value = getRandomElement(aMap.get(key));