2012-03-18 23 views
6

Utilizando las nuevas colecciones de Google Guava, http://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained¿Cómo iterar sobre Multimap en el orden de inserción?

¿Cómo repito sobre un MultiMap para cada clave en el orden de inserción?

Por ejemplo

multimap = new HashMultiMap<String,String>(); 
multimap.put("1", "value1"); 
multimap.put("1", "value2"); 
multimap.put("1", "value3"); 

multimap.put("2", "value11"); 
multimap.put("2", "value22"); 
multimap.put("2", "value33"); 

multimap.put("3", "value111"); 
multimap.put("3", "value222"); 
multimap.put("3", "value333"); 

En cada bucle que necesito

"value1", "value11", "value111"; 

entonces el siguiente bucle

"value2", "value22", "value222"; 

y así sucesivamente:

"value3", "value33", "value333"; 
+4

Las colecciones 'Hash *' no conservan el orden de inserción. – SLaks

+0

parece que necesito usar Table not a MultiMap – KJW

Respuesta

11

No estoy muy seguro cuáles son sus necesidades (o caso de uso concreto), pero intentaré adivinar. Otras respuestas sugieren usar Linked * Multimap o Inmutable, pero para obtener la salida deseada (mostrada en cuestión) con Multimap, tendrá que crear un mapa elegante (lo discutiré más adelante) o, por ejemplo, crear tres colecciones temporales que contengan primero, segundo y terceros valores para cada clave (estarán en orden de inserción, si usa una de las implementaciones Multimap sugeridas). Preferiblemente sería uno de ListMultimaps como se puede iterar sobre multimap.keySet() obtener listas con los valores disponibles por el índice:

final ListMultimap<String,String> multimap = LinkedListMultimap.create(); 
// put values from question here 

final List<Object> firstValues = Lists.newArrayList(); 
for (final String key: multimap.keySet()) { 
    firstValues.add(multimap.get(key).get(0)); 
}  
System.out.println(firstValues); 
// prints [value1, value11, value111] 
// similar for multimap.get(key).get(1) and so on 

pero la desventaja es que usted tendrá que crear tres listas para usted ejemplo, lo que hace que esta solución en lugar inflexibleAsí que tal vez será mejor que poner {primera, segunda, tercera} valores de la colección a Mapa>, lo que me lleva al punto:


tal vez debería utilizar Table en su lugar?

tabla está diseñada como Una colección que asocia un par ordenado de claves, una clave llamada fila y una columna de clave, con un único valor y, lo que es más importante en este caso, tiene fila y vistas de columnas. Voy a usar ArrayTable aquí:

final ArrayTable<String, Integer, Object> table = ArrayTable.create(
    ImmutableList.of("1", "2", "3"), ImmutableList.of(0, 1, 2)); 

table.put("1", 0, "value1"); 
table.put("1", 1, "value2"); 
table.put("1", 2, "value3"); 

table.put("2", 0, "value11"); 
table.put("2", 1, "value22"); 
table.put("2", 2, "value33"); 

table.put("3", 0, "value111"); 
table.put("3", 1, "value222"); 
table.put("3", 2, "value333"); 

for (final Integer columnKey : table.columnKeyList()) { 
    System.out.println(table.column(columnKey).values()); 
} 
// prints: 
// [value1, value11, value111] 
// [value2, value22, value222] 
// [value3, value33, value333] 

he usado deliberadamente cadena de teclas de la fila, que son [1, 2, 3, ...] enteros en realidad (como lo hizo en la pregunta) y enteros para las claves de columna comenzando con 0 ([0, 1, 2, ...]) para mostrar similitud con el ejemplo anterior usando el get(int) de List en la colección de valores de multimaps.

la esperanza que esto sea útil, sobre todo en la determinación de lo que quiere;)

P. S. Yo uso ArrayTable aquí, porque tiene una manera más clara de crear un conjunto fijo (universo) de filas/claves que ImmutableTable, pero si no se requiere mutabilidad, debe usarlo en cambio con un cambio - ImmutableTable (y cualquier otra implementación de tabla) doesn No tiene el método columnKeyList(), pero solo columnKeySet() que hace lo mismo, pero es más lento para ArrayTable. Y, por supuesto, se deben usar ImmutableTable.Builder o ImmutableTable.copyOf(Table).

+1

Terminé usando la tabla, y repito sobre cada fila, para obtener un mapa que representa toda la fila. – KJW

2

para recorrer a través de múltiples claves:

for (Object key : multimap.keys()) { ... } 

También puede bucle sobre las entradas:

for (Map.Entry entry : multimap.entries()) { ... } 
+0

aquí es donde estoy confundido, lo vi en una pregunta anterior pero no estaba seguro de cómo funciona esto? ¿Devuelve todos los valores para una clave específica o devuelve cada valor asociado con las claves? ¿Hay algún ejemplo de esto en acción? – KJW

4

Puede utilizar cualquiera LinkedListMultimap o LinkedHashMultimap.

Ambos tienen un comportamiento muy similar; una diferencia importante es que LinkedListMultimap permite que se inserten varias copias del mismo par clave-valor, mientras que LinkedHashMultimap permite solo una.

Consulte el Javadoc vinculado anteriormente para obtener más información.

+0

No estoy seguro del primer punto. Intenté con un ejemplo en ejecución y el orden de iteración usando los dos multimaps es el mismo usando claves, valores, entradas y asMap. – dawww

+1

@dawww: Oops, tienes razón. Debo haber leído mal la documentación. Eliminaré ese punto, gracias. :-) – ruakh

3

No estoy del todo claro lo que quiere decir orden de iteración, OP ...

  • Set<K> keySet() sólo devuelve las llaves.
  • Map<K, Collection<V>> asMap() devuelve las claves y sus entradas asociadas, por lo que puede hacer for (Map.Entry<K, Collection<V>> entry : asMap().entrySet()) para iterar sobre las claves y sus colecciones asociadas.
  • Collection<Map.Entry<K, V>> entries() le permite repetir las entradas, pero sin agruparlas necesariamente por clave.

Si quieres que las cosas en el orden de inserción, utilice uno de los Multimap implementaciones de inserción ordenada - LinkedHashMultimap, posiblemente LinkedListMultimap, ImmutableMultimap.

Cuestiones relacionadas