I have a function that accepts a HashMap<String, HashSet<Integer>>
. Now I want to get a random value from the HashMap
but I don't know how to do this. Could you give me a hint?
The output should consist of a tuple containing the String
and an Integer
value.
Knowing the size of the map, you could pick a random entry number, then iterate over the contents until you reach that entry. Example:
final Set<String> keys = allowedInput.keySet();
final int keyNumber = (int)(Math.random() * keys.size());
final Iterator<String> keyIterator = keys.iterator();
String randomKey = null;
for (int i = 0; i < keyNumber && keyIterator.hasNext(); i++) {
randomKey = keyIterator.next();
}
if (randomKey == null) {
// This should not happen unless the map was empty, or it was modified
// externally. Handle the potential error case accordingly.
}
final HashSet<Integer> value = allowedInput.get(randomKey);
// `value` now contains a random element from the `allowedInput` map.
If you want to retrieve a random Integer
element from the resulting HashSet<Integer>
, then you can adapt the same technique: simply pick a random element number based on the size of the set, and iterate over the contents until you find it.
If you want to repeatedly get random values, you could shuffle the set, and then go through it in order.
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));
thx evry one for the help i got i working now this is the code i used
final Set<String> keys = allowedInput.keySet();
int keyNumber = (int)(random.nextInt(keys.size()));
final Iterator<String> keyIterator = keys.iterator();
String key = null;
for (int i = 0; i <= keyNumber; i++) {
key = keyIterator.next();
}
if (key == null) {
// handle empty map
}
HashSet<Integer> field = allowedInput.get(key);
final int fieldNumber = (int)(random.nextInt(field.size()));
int fieldID = 0;
int i = 0;
for(Object obj : field)
{
if (i == fieldNumber)
{
//fieldID = Integer.parseInt(obj.toString());
fieldID = (int)obj;
break;
}
i = i + 1;
}
// Start constructing the userinput
// Note: we need an instance of the UserInputSystem to create the UserInput instance!
UserInputSystem userInputSystem = new UserInputSystem();
UserInput input = userInputSystem.new UserInput(fieldID, key);
System.err.println("ai fieldID = "+fieldID+" key = "+key);
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.