2010-10-09 7 views
11

Tengo un LinkedHashMap. Quiero conseguir el Foo en el índice N. ¿Hay una mejor manera de hacer esto, además de la iteración hasta que lo encuentre ?:¿Deseas encontrar una entrada de Mapa en un índice?

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

que tengo que hacer llegar los elementos al azar del mapa por un índice de cerca de 50 veces alguna operación. El mapa tendrá alrededor de 20 elementos.

Gracias

Respuesta

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

Entonces para el índice de N con O (1) de acceso ...

randAccess.get(N) 
+5

Usted ha pasado O (N) creando una copia de todas las claves en el mapa. Si se inserta algo en el mapa, su copia no se actualizará. * Solo es O (1) para consultas sucesivas después de la copia inicial *. – tucuxi

3

@ solución de Mark es el clavo. Solo me gustaría señalar que las compensaciones (posiciones) de las entradas en un mapa (de cualquier tipo) no son estables. Cada vez que se agrega o elimina una entrada, las compensaciones de las entradas restantes pueden cambiar. Para un HashMap o LinkedHashMap, no hay forma de saber qué cambios de entrada cambiarán.

  • Para un HashMap regular, una sola inserción puede aparentemente "aleatorizar" los desplazamientos de entrada.
  • Para un LinkedHashMap, el orden de las entradas es estable, los desplazamientos de entrada reales no lo son.

La inestabilidad de los desplazamientos y el hecho de que la búsqueda de la entrada a un offset dado es caro para todas las implementaciones de mapa estándar son las razones por las que la interfaz Map no proporciona un método get(int offset). También debería ser una pista de que no es una buena idea que un algoritmo necesite hacer este tipo de cosas.

+0

Creo que podría haber tenido el mismo comentario, excepto que el OP está utilizando un LinkedHashMap que mantiene una lista vinculada de las entradas correspondientes al orden de inserción para la iteración ... por lo tanto, el orden de iteración es estable en el tiempo ... ¿no? –

0

Una simplificación de la solución de @ Mark ... Solo necesita los valores, por lo que cada vez que cambie un valor en el Mapa de foos, también actualice una matriz.

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 de guayaba puede ayudar en este caso:

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

see javadoc: Iterables.get

Para su caso, el código puede ser como este:

Iterables.get(foos.values(), N); 
Cuestiones relacionadas