Der beste Weg, einen hashmap von Arraylist erstellen
-
06-07-2019 - |
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?
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
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.