2009-06-18 20 views
24

Tengo un millón de filas de datos en formato .txt. el formato es muy simple. Para cada fila:La mejor manera de crear un hashmap de arraylist

 
user1,value1 
user2,value2 
user3,value3 
user1,value4 
... 

Usted sabe a qué me refiero. Para cada usuario, podría aparecer muchas veces, o aparecer solo una vez (nunca se sabe). Necesito encontrar todos los valores para cada usuario. Debido a que el usuario puede aparecer de forma aleatoria, utilicé Hashmap para hacerlo. Es decir: HashMap (clave: String, valor: ArrayList). Pero para agregar datos al arrayList, tengo que usar constantemente HashMap get (key) para obtener el arrayList, agregarle valor y luego ponerlo nuevamente en HashMap. Siento que no es tan eficiente. ¿Alguien sabe una mejor manera de hacer eso?

Respuesta

61

No necesita volver a agregar ArrayList a su Mapa. Si ArrayList ya existe, solo agregue su valor.

una mejor aplicación podría ser:

Map<String, Collection<String>> map = new HashMap<String, Collection<String>>(); 

al procesar cada línea:

String user = user field from line 
String value = value field from line 

Collection<String> values = map.get(user); 
if (values==null) { 
    values = new ArrayList<String>(); 
    map.put(user, values) 
} 
values.add(value); 

Seguimiento de abril de 2014 - Me escribió la respuesta original de nuevo en 2009, cuando mi conocimiento de Google Guava era limitado. A la luz de todo lo que hace Google Guava, ahora recomiendo usar su Multimap en lugar de reinventarlo.

Multimap<String, String> values = HashMultimap.create(); 
values.put("user1", "value1"); 
values.put("user2", "value2"); 
values.put("user3", "value3"); 
values.put("user1", "value4"); 

System.out.println(values.get("user1")); 
System.out.println(values.get("user2")); 
System.out.println(values.get("user3")); 

Salidas:

[value4, value1] 
[value2] 
[value3] 
+0

Otras respuestas son todas correctas. Simplemente no quiero usar bibliotecas externas. –

+0

Esto fue un salvavidas, gracias. – wirbly

-1

sería más rápido si usaba una lista enlazada en lugar de una lista de arreglos, ya que ArrayList necesitará cambiar el tamaño cuando se acerque a su capacidad.

, también querrá estimar de forma adecuada la capacidad de la colección de envoltura (HashMap o Multimap) que está creando para evitar el reaprovisionamiento repetitivo.

+2

ArrayList seguramente tendrá un mejor rendimiento promedio, incluso con el cambio de tamaño. LinkedList es una buena opción cuando desea que todas sus operaciones tarden más o menos al mismo tiempo, por ejemplo, están involucradas en la IU y no desea retrasos aleatorios cuando el usuario realiza una acción. –

4

Los valores de ArrayList en su HashMap son referencias. No necesita "volver a ponerlo en HashMap". Está operando en el objeto que ya existe como un valor en HashMap.

-1

Como ya se ha mencionado, MultiMap es su mejor opción.

Dependiendo de los requisitos de su negocio o las limitaciones en el archivo de datos, es posible que desee considerar hacer una clasificación de una sola vez, para hacerlo más optimizado para la carga.

+1

Esto debería ser un comentario –

0

No pude encontrar ninguna manera fácil. MultiMap no siempre es una opción disponible. Entonces escribí algo así.

public class Context<K, V> extends HashMap<K, V> { 

    public V addMulti(K paramK, V paramV) { 
     V value = get(paramK); 
     if (value == null) { 
      List<V> list = new ArrayList<V>(); 
      list.add(paramV); 
      put(paramK, paramV); 
     } else if (value instanceof List<?>) { 
      ((List<V>)value).add(paramV); 
     } else { 
      List<V> list = new ArrayList<V>(); 
      list.add(value); 
      list.add(paramV); 
      put(paramK, (V) list); 
     } 
     return paramV; 
    } 
} 
3

Si no quiere importar una biblioteca.

package util;  

import java.util.ArrayList;  
import java.util.HashMap;  
import java.util.List;  

/**  
* A simple implementation of a MultiMap. This implementation allows duplicate elements in the the  
* values. (I know classes like this are out there but the ones available to me didn't work).  
*/  
public class MultiMap<K, V> extends HashMap<K, List<V>> {  

    /**  
    * Looks for a list that is mapped to the given key. If there is not one then a new one is created  
    * mapped and has the value added to it.  
    *  
    * @param key  
    * @param value  
    * @return true if the list has already been created, false if a new list is created.  
    */  
    public boolean putOne(K key, V value) {  
    if (this.containsKey(key)) {  
     this.get(key).add(value);  
     return true;  
    } else {  
     List<V> values = new ArrayList<>();  
     values.add(value);  
     this.put(key, values);  
     return false;  
    }  
    }  
}  
+0

Un buen ejemplo de una solución core API de Java. Gracias, – Loa

Cuestiones relacionadas