La selezione casuale chiave e valore imposta da una Mappa in Java

Voglio ottenere dei tasti a caso e i loro rispettivi valori di una Mappa. L’idea è che un generatore casuale sarebbe scegliere una chiave e la visualizzazione del valore. La parte difficile è che sia la chiave e il valore sarà stringhe, per esempio myMap.put("Geddy", "Lee").

  • Quali sono i tuoi criteri di performance? C’è un O(n) soluzione per scegliere un elemento casuale da una sequenza arbitraria, ma se si sta andando ad essere raccolta casuale di elementi molto dalla mappa, si potrebbe desiderare di creare un elenco di chiavi, in modo che si può semplicemente scegliere un numero casuale e andare da loro.
  • Ho due modi che io immagino questo: un tasto viene chiamato in modo casuale e visualizzato l’utente immette un valore, il valore immesso viene confrontato con il valore memorizzato con la chiave. Dal mio esempio di cui sopra, diciamo che l’utente è chiesto “Qual è il Geddy cognome?” (dove “Geddy” dovrebbe essere preso come una stringa dalla chiave), l’utente immette “Smith”. “Smith” è confrontati con il valore di “Lee”, ecc…
InformationsquelleAutor Roberto | 2012-03-29

 

8 Replies
  1. 48
    HashMap<String, String> x;
    
    Random       random    = new Random();
    List<String> keys      = new ArrayList<String>(x.keySet());
    String       randomKey = keys.get( random.nextInt(keys.size()) );
    String       value     = x.get(randomKey);
    • Vorrei porre l’entrySet() nell’Elenco.
    • Grazie! Che è stato davvero utile.
    • Devo aggiungere che non ho rivelare che ho dovuto implementare questo in Android. Alla fine ho finito per usare SharedPreferences -> Mappa e Mappa -> ArrayList.
    • Funzionato come un fascino
  2. 3

    Se non ti dispiace lo spazio sprecato, un approccio sarebbe separatamente mantenere un List di tutte le chiavi che si trovano nella Map. Per prestazioni ottimali, si vorrà un List che ha un buon accesso casuale prestazioni (come un ArrayList). Quindi, ottenere un numero casuale compreso tra 0 (incluso) e list.size() (in esclusiva), estrarre la chiave di tale indice, e guarda che il tasto up.

    Random rand = something
    int randIndex = rand.nextInt(list.size());
    K key = list.get(randIndex);
    V value = map.get(key);

    Questo approccio significa anche che l’aggiunta di una coppia chiave-valore è un buon affare più conveniente che la rimozione di uno. Per aggiungere la coppia chiave-valore, si potrebbe verificare per vedere se la chiave è già in mappa (se i vostri valori possono essere null, dovrete separatamente chiamata map.containsKey; se non, si può solo aggiungere la coppia chiave-valore e vedere se il “valore storico” che ritorna è null). Se la chiave è già nella mappa, l’elenco è invariato, ma se non, si aggiunge la chiave per la lista (un’operazione O(1) per la maggior parte delle liste). Rimozione di una coppia chiave-valore, anche se comporta una O(N) operazioni per rimuovere la chiave dall’elenco.

    Se lo spazio è una grande preoccupazione, ma le prestazioni non di meno, si potrebbe anche ottenere un Iterator sulla mappa della voce (Map.entrySet()), e saltare randIndex voci prima di tornare a quello che si desidera. Ma sarebbe un O(N) operazioni, che genere di sconfitte il punto di tutta la mappa.

    Infine, è possibile trovare la voce del toArray() e casualmente indice nell’. Più semplice, anche se meno efficiente.

    • Questo è stato davvero utile.
  3. 2

    se le chiavi sono di interi, o qualcosa di simile, si può utilizzare il diagramma ad albero per farlo.

    TreeMap<Integer, Integer> treeMap = new TreeMap<>();
    int key = RandomUtils.ranInt(treeMap.lastKey());
    int value = treeMap.ceilingKey(key);
  4. 1

    Vorrei copiare la Mappa in un array e selezionare la voce che si desidera a caso. Questo evita la necessità di ricerca il valore della chiave.

    Map<String, String> x = new HashMap<String, String>();
    Map.Entry<String,String>[] entries = x.entrySet().toArray(new Map.Entry[0]);
    Random rand = new Random();
    
    //call repeatedly
    Map.Entry<String, String> keyValue = entries[rand.nextInt(entries.length)];

    Se si desidera evitare la duplicazione, è possibile randomizzare l’ordine delle voci

    Map<String, String> x = new HashMap<String, String>();
    List<Map.Entry<String,String>> entries = new ArrayList<Map.Entry<String, String>> (x.entrySet());
    Collections.shuffle(entries);
    for (Map.Entry<String, String> entry : entries) {
        System.out.println(entry);
    }
  5. 1

    Utilizzare serbatoio di campionamento per selezionare un elenco di tasti a caso, quindi inserire in una mappa (insieme con i loro corrispondenti valori nella mappa di origine.)

    In questo modo non è necessario copiare l’intero keySet in un array, solo i tasti selezionati.

    public static <K, V>Map<K, V> sampleFromMap(Map<? extends K, ? extends V> source, int n, Random rnd) {
        List<K> chosenKeys = new ArrayList<K>();
        int count = 0;
        for (K k: source.keySet()) {
            if (count++ < n) {
                chosenKeys.add(k);
                if (count == n) {
                    Collections.shuffle(chosenKeys, rnd);
                }
            } else {
                int pos = rnd.nextInt(count);
                if (pos < n) {
                    chosenKeys.set(pos, k);
                }
            }
        }
        Map<K, V> result = new HashMap<K, V>();
        for (K k: chosenKeys) {
            result.put(k, source.get(k));
        }
        return Collections.unmodifiableMap(result);
    }
    • Cercherò in questo ulteriore.
    • Anche se questo è valido in teoria, non keySet() già allocate in un
  6. 0
    In some cases you might want to preserve an order you put the elements in the Set,
    In such scenario you can use, This 
    
    Set<Integer> alldocsId = new HashSet<>();
                for (int i=0;i<normalized.length;i++)
                {
                    String sql = "SELECT DISTINCT movieID FROM postingtbl WHERE term=?";
                    PreparedStatement prepstm = conn.prepareStatement(sql);
                    prepstm.setString(1,normalized[i]);
                    ResultSet rs = prepstm.executeQuery();
                    while (rs.next())
                    {
                        alldocsId.add(rs.getInt("MovieID"));
                    }
                    prepstm.close();
                }
    
            List<Integer> alldocIDlst = new ArrayList<>();
            Iterator it = alldocsId.iterator();
            while (it.hasNext())
            {
                alldocIDlst.add(Integer.valueOf(it.next().toString()));
            }
  7. -1

    Stato un po ‘ giocato con java, ma non keySet() fornire un elenco che è possibile selezionare tramite un indice numerico? Penso che si potrebbe scegliere un numero casuale e selezionare il keySet di myMap, quindi selezionare il corrispondente valore da myMap. Posso provare in questo momento, ma sembra che mi colpiscono possibile!

    • No, come suggerisce il nome, che restituisce un Set e non un List. Quindi sì, si può prendere una chiave casuale da un Set ma non così semplice, né veloce), come da List

Lascia un commento