2011-01-29 359 views
9

Quiero añadir elementos duplicados en HashMapJava HashMap elementos duplicados

manera:

put("name1", 1); 
put("name1", 3); 
put("name1", 3); 
put("name2", 1); 
put("name2", 3); 

cómo puedo hacer eso?

+0

¿cuál es el beneficio de hacer esto? ¿Qué estás tratando de lograr, tal vez hay una mejor manera de hacerlo si le das más deatils – ant

Respuesta

13

Utilice un Map<String, List<Integer>> es decir, asigna una cadena a una lista de números enteros.

Por lo tanto, en este caso, name1 se correlacionaría con una lista de [1,3,3].

Obviamente tendrías que escribir tu propio método de poner, en el cual agregas el int a la lista. Ejemplo:

put(String s, int i){ 
    List<Integer> list = map.get(s); 
    if(list == null){ 
     list = new ArrayList<Integer>(); 
     map.put(s, list); 
    } 
    list.add(i); 
} 
0

No puede, pero puede crear su propia implementación de mapa que permita duplicados en su interior.

+2

Si permite duplicados, no es un 'Mapa'. – finnw

+0

@finnw true (pad ..) – ant

+0

bien, ¿no hay ningún "mapa" que permita eso? ¿cual es el nombre de esto? – lacas

13

La interfaz ListMultimap de Guava puede cumplir sus requisitos. Permite duplicar claves y duplicar pares clave/valor.

ListMultimap<String, Integer> m = 
    ArrayListMultimap.create(); 
m.put("name1", 1); 
m.put("name1", 3); 
m.put("name1", 3); 
m.put("name2", 1); 
m.put("name2", 3); 
System.out.println(m.get("name1")); // => [1, 3, 3] 
System.out.println(m.get("name2")); // => [1, 3] 

¿De verdad necesita conservar los pares clave/valor duplicados? (. Y más eficiente) Si no, entonces un HashMultimap puede ser suficiente Si inserta las mismas entradas en un HashMultimap que se obtiene:

System.out.println(m.get("name1")); // => [1, 3] 
System.out.println(m.get("name2")); // => [1, 3] 
+0

+1 - esto es lo que habría hecho. – CoolBeans

5

Tu idea viola el contrato de la interfaz Map:

An object that maps keys to values. A map cannot contain duplicate keys; each key can map to at most one value.

sería comprensible que ser confuso para el mapa cuando se preguntan:

map.get("name1") 

se no sabría qué valor obtener.

Usaría la solución de dogbane para asignar cada clave a una lista de enteros. En su ejemplo, tiene posibles valores duplicados. Si no desea valores duplicados (es decir, para "nombre1", solo habría un 3 en la lista resultante), podría convertirlo en un Mapa de cadenas en Sets de enteros.

3

Debe utilizar la estructura de datos Multimap de Google Collection.

Una colección similar a un mapa, pero que pueden asociar varios valores con una sola llave. Si llama put (K, V) dos veces, con la misma clave pero valores diferentes, el multimap contiene asignaciones desde la clave a ambos valores .

Esto es exactamente lo que está tratando de lograr. No hay necesidad de reinventar la rueda escribiendo sus operaciones de Mapa personalizadas en mi opinión. También puede encontrar este tutorial en MultiMap útil.

+0

Más específicamente, creo que debería ser un 'ListMultimap'. Un 'SetMultimap' no permitiría pares duplicados de clave/valor, pero hay uno en la entrada de ejemplo. Ese artículo está un poco desactualizado. Desde entonces, Google Collections se ha fusionado en [Guava] (http://code.google.com/p/guava-libraries/). – finnw

+0

Derecha. O puede usar HashMultimap – CoolBeans

+0

'HashMultimap' sí permite duplicar claves pero no duplicar pares clave/valor. Si inserta las entradas de ejemplo en un 'HashMultimap' terminará con una sola entrada' name1 = 3'. – finnw

0

org.apache.commons.collections.map.MultiValueMap es una opción más adecuada. Puede poner una clave en varios valores.

public Object put(Object key, Object value) { 
    boolean result = false; 
    Collection coll = getCollection(key); 
    if (coll == null) { 
     coll = createCollection(1); 
     result = coll.add(value); 
     if (coll.size() > 0) { 
      // only add if non-zero size to maintain class state 
      getMap().put(key, coll); 
      result = false; 
     } 
    } else { 
     result = coll.add(value); 
    } 
    return (result ? value : null); 
}