web-dev-qa-db-fra.com

Existe-t-il un moyen d'obtenir la valeur d'un HashMap au hasard en Java?

Existe-t-il un moyen d'obtenir la valeur d'un HashMap au hasard en Java?

30
Varuna

Vous pourriez utiliser quelque chose comme:

Random generator = new Random();
Map.Entry[] entries = myHashMap.entrySet().toArray();
randomValue = entries[generator.nextInt(entries.length)].getValue();

Mettre à jour.

Le ci-dessus ne fonctionne pas , Set.toArray() renvoie toujours un tableau de Objects, qui ne peut pas être forcé dans un tableau de Map.Entry.

Ceci (version plus simple) fonctionne:

Random generator = new Random();
Object[] values = myHashMap.values().toArray();
Object randomValue = values[generator.nextInt(values.length)];

Si vous voulez que la valeur aléatoire soit d'un type autre que Object, ajoutez simplement un transtypage à la dernière ligne. Donc, si myHashMap a été déclaré comme:

Map<Integer,String> myHashMap = new HashMap<Integer,String>();

La dernière ligne peut être:

String randomValue = (String) values[generator.nextInt(value.length)];
48
Tom Jefferys

Puisque les exigences ne demandent qu'une valeur aléatoire à partir de HashMap, voici l'approche:

  1. Le HashMap a une méthode values qui retourne un Collection des valeurs de la carte.
  2. La Collection est utilisée pour créer un List .
  3. La méthode size est utilisée pour trouver la taille de la List, utilisée par la méthode Random.nextInt pour obtenir un index aléatoire de la List.
  4. Enfin, la valeur est extraite de la méthode Listget avec l'index aléatoire.

La mise en oeuvre:

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);

La partie sympa de cette approche est que toutes les méthodes sont génériques - il n’est pas nécessaire de recourir à la conversion.

28
coobird

Si vous devez tirer d'autres valeurs de la carte sans répéter aucun élément, vous pouvez la placer dans une liste, puis la mélanger.

List<Object> valuesList = new ArrayList<Object>(map.values());
Collections.shuffle( valuesList );

for ( Object obj : valuesList ) {
    System.out.println( obj );
}
10
banjollity

Générez un nombre aléatoire compris entre 0 et le nombre de clés de votre HashMap. Obtenez la clé au nombre aléatoire. Obtenez la valeur de cette clé.

Pseudocode :

 int n =  random(map.keys().length());
 String key = map.keys().at(n);
 Object value = map.at(key);

S'il est difficile d'implémenter cela en Java, vous pouvez créer un tableau à partir de ce code en utilisant la fonction toArray() dans Set.

 Object[] values = map.values().toArray(new Object[map.size()]);
 Object random_value = values[random(values.length)];

Je ne sais pas trop comment faire le nombre aléatoire.

3
Peter Stuifzand

J'ai écrit un utilitaire pour extraire une entrée, une clé ou une valeur aléatoire d'une carte, d'un ensemble d'entrées ou d'un itérateur.

Comme vous ne pouvez pas et ne devriez pas pouvoir déterminer la taille d'un itérateur ( Guava peut le faire ), vous devrez surcharger la méthode randEntry() pour accepter une taille qui devrait être la longueur des entrées.

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();
    }
}
0
Mr. Polywhirl

Voici un exemple d'utilisation de l'approche par tableaux décrite par Peter Stuifzand, également via la méthode values()-:

// 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) );
0
MH114

je ne sais vraiment pas pourquoi vous voulez faire cela ... mais si cela aide, j'ai créé une RandomMap qui randomise automatiquement les valeurs lorsque vous appelez values ​​(), alors l'application de démonstration exécutable suivante pourrait faire l'affaire. . 

  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;
      }

  }
0
kctang

Habituellement, vous ne voulez pas vraiment une valeur random mais plutôt juste any value, et puis c'est agréable de faire ceci:

Object selectedObj = null;
for (Object obj : map.values()) {
    selectedObj = obj;
    break;
}
0
Kalisky

La conversion en tableau et l'obtention de la valeur sont trop lents lorsque vous vous trouvez dans le chemin d'accès rapide.

alors récupérez l'ensemble (soit la clé, soit la valeur de la clé) et faites quelque chose comme:

    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();
    }
0
Quonux