2010-10-09 15 views
11

Ho una LinkedHashMap. Voglio ottenere il Foo di indice N. Esiste un modo migliore di fare questo, oltre l'iterazione fino a quando trovo ?:Iterate per trovare una voce Mappa in un indice?

int target = N; 
int index = 0; 
for (Map.Entry<String, Foo> it : foos.entrySet()) { 
    if (index == target) { 
     return it.getValue(); 
    } 
    index++; 
} 

devo fare ottenere elementi casuali dalla mappa da un indice di circa 50 volte per qualche operazione La mappa avrà circa 20 elementi in essa contenuti.

Grazie

risposta

14
List<Entry<String,Foo>> randAccess = new ArrayList<Entry<String,Foo>>(foos.entrySet()); 

Poi per l'indice N con O (1) accesso ...

randAccess.get(N) 
+5

Hai speso O (N) creando una copia di tutte le chiavi nella mappa. Se qualcosa viene inserito nella mappa, la tua copia non verrà aggiornata. * È solo O (1) per le query successive dopo la copia iniziale *. – tucuxi

3

@ soluzione di Mark è a posto. Vorrei solo sottolineare che gli offset (posizioni) delle voci in una mappa (di qualsiasi tipo) non sono stabili. Ogni volta che una voce viene aggiunta o rimossa, gli scostamenti delle voci rimanenti possono cambiare. Per una HashMap o LinkedHashMap, non hai modo di sapere quale offset della voce cambierà.

  • Per una normale HashMap, un singolo inserimento può apparentemente "randomizzare" gli offset di entrata.
  • Per una LinkedHashMap, l'ordine delle voci è stabile, gli offset di entrata effettivi non lo sono.

L'instabilità delle compensazioni e il fatto che trovare l'ingresso in un dato offset è costoso per tutti mappa implementazioni standard sono i motivi per cui l'interfaccia Map non fornisce un metodo get(int offset). Dovrebbe anche essere un suggerimento che non è una buona idea che un algoritmo debba fare questo genere di cose.

+0

Penso che avrei potuto avere lo stesso commento, tranne che l'OP utilizza una LinkedHashMap che mantiene un elenco collegato delle voci corrispondenti all'ordine di inserimento per l'iterazione ... quindi l'ordine di iterazione è stabile nel tempo ... no? –

0

Una semplificazione della soluzione di @ Mark ... Sono necessari solo i valori, quindi ogni volta che si modifica un valore nella mappa foos, aggiornare anche un array.

Map<String, Foo> foos =; 
Foo[] fooValues = {}; 

foos.put(foos.name(), foo); 
fooValues = foos.values().toArray(new Foo[foos.size()]); 

// later 
Foo foo = fooValues[N]; 
0

biblioteca Guava può aiutare in questo caso:

public static <T> T com.google.common.collect.Iterables.get(Iterable<T> iterable, int position) 

see javadoc: Iterables.get

Per il vostro caso il codice può essere simile a questo:

Iterables.get(foos.values(), N); 
Problemi correlati