Frage

Ich habe eine Million Zeilen von Daten im .txt-Format. Das Format ist sehr einfach. Für jede Zeile:

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

Sie wissen, was ich meine. Für jeden Benutzer, könnte es oft erscheinen, oder gibt es nur einmal (man weiß ja nie). Ich brauche alle Werte für jeden Benutzer zu erfahren. Da Benutzer zufällig erscheinen, benutzte ich HashMap es zu tun. Das heißt: HashMap (key: String, value: Arraylist). Aber fügen Sie Daten zu dem Arraylist, habe ich immer wieder verwenden HashMap (key) erhalten die Arraylist zu erhalten, fügen Sie Wert darauf, es dann zu HashMap zurückstellen. Ich glaube, es ist nicht so sehr effizient. Jeder kennt einen besseren Weg, das zu tun?

War es hilfreich?

Lösung

Sie brauchen nicht die Arraylist zurück auf Ihre Karte erneut hinzuzufügen. Wenn die Arraylist existiert bereits dann fügen Sie einfach Ihren Wert zu.

Eine verbesserte Implementierung könnte wie folgt aussehen:

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

Bei der Verarbeitung jeder Zeile:

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);

Follow-up April 2014 - ich die ursprüngliche Antwort zurück im Jahr 2009 schrieb, als mein Wissen über Google Guava begrenzt war. In Anbetracht all das, was Google tut Guava, empfehle ich jetzt seinen Multimap statt neu zu erfinden Sie es.

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"));

Ausgänge:

[value4, value1]
[value2]
[value3]

Andere Tipps

Mit Multimap von Google-Kollektionen. Es können mehrere Werte für den gleichen Schlüssel

https: / /google.github.io/guava/releases/19.0/api/docs/com/google/common/collect/Multimap.html

Die Arraylist Werte in Ihrer HashMap Referenzen sind. Sie brauchen nicht zu „um es HashMap zu setzen“. Sie arbeitet auf dem Objekt, das bereits als Wert in der HashMap vorhanden ist.

Wenn Sie nicht wollen, um eine Bibliothek importieren.

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;    
    }    
  }    
}    

Da Java 8 Sie können map.computeIfAbsent verwenden

https://docs.oracle.com/javase/8/docs/api/java/util/Map.html#computeIfAbsent-K-java.util.function.Function-

Collection<String> values = map.computeIfAbsent(user, k -> new ArrayList<>());
values.add(value);

Ich denke, was Sie wollen, ist die Multimap. Sie können es von commons Sammlung Apache bekommen, oder google-Sammlungen.

http://commons.apache.org/collections/

http://code.google.com/p/google-collections/

  

"Sammlung ähnlich eine Karte, aber   welche mehrere Werte zugeordnet werden können   mit einem einzigen Schlüssel. Wenn Sie rufen setzen (K,   V) zweimal mit dem gleichen Schlüssel aber   verschiedene Werte, die multimap   enthält Mappings von dem Schlüssel sowohl   Werte. "

Ich kann keine einfache Möglichkeit finden. MultiMap ist nicht immer eine Option zur Verfügung. Also schrieb ich etwas mit diesem.

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;
    }
}

wäre es schneller, wenn Sie eine LinkedList statt einer Arraylist verwendet, da die Arraylist, um die Größe benötigen, wenn es Kapazität nähert.

Sie wollen auch die Kapazität der Verpackungssammlung (HashMap oder Multimap) in geeigneter Weise schätzen Sie sich wiederholendes Wiederkäuen zu vermeiden schaffen.

Wie bereits erwähnt, MultiMap ist die beste Option.

Je nach Ihren geschäftlichen Anforderungen oder Einschränkungen für die Datendatei, sollten Sie tun, eine einmalige davon Sortierung zu betrachten, ist es für die Beladung optimiert zu machen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top