创建arraylist的hashmap的最佳方法

我有.txt格式的一百万行数据。 格式很简单。 对于每一行:

 USER1,值1
用户2,值2
用户3,值3
 USER1,VALUE4
 ...

你知道我的意思。 对于每个用户,它可能会出现多次,或只出现一次(您永远不会知道)。 我需要找出每个用户的所有值。 因为用户可能会随机出现,所以我使用Hashmap来做。 即:HashMap(key:String,value:ArrayList)。 但是要向arrayList添加数据,我必须经常使用HashMap get(key)来获取arrayList,为它添加值,然后将其放回HashMap。 我觉得效率不高。 谁知道更好的方法呢?

您无需将ArrayList重新添加回Map。 如果ArrayList已经存在,那么只需将值添加到它。

改进的实现可能如下所示:

Map> map = new HashMap>(); 

处理每一行时:

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

20144月的后续行动 – 当我对Google Guava的知识有限时,我在2009年写了原始答案。 鉴于Google Guava所做的一切,我现在建议使用其Multimap而不是重新发明它。

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

输出:

 [value4, value1] [value2] [value3] 

使用Google Collections中的Multimap。 它允许同一个键的多个值

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

HashMap中的ArrayList值是引用。 你不需要“把它放回HashMap”。 您正在对作为HashMap中的值已存在的对象进行操作。

如果您不想导入库。

 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 extends HashMap> { /** * 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 values = new ArrayList<>(); values.add(value); this.put(key, values); return false; } } } 

我想你想要的是Multimap。 你可以从apache的commons集合或google-collections中获取它。

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

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

“集合类似于Map,但可以将多个值与一个键相关联。如果您使用相同的键但不同的值调用put(K,V)两次,则multimap包含从键到两个值的映射。”

我找不到任何简单的方法。 MultiMap并不总是可用的选项。 所以我写了一些东西。

 public class Context extends HashMap { public V addMulti(K paramK, V paramV) { V value = get(paramK); if (value == null) { List list = new ArrayList(); list.add(paramV); put(paramK, paramV); } else if (value instanceof List) { ((List)value).add(paramV); } else { List list = new ArrayList(); list.add(value); list.add(paramV); put(paramK, (V) list); } return paramV; } } 

Java 8您可以使用map.computeIfAbsent

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

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

如果使用LinkedList而不是ArrayList会更快,因为ArrayList在接近容量时需要resize。

您还需要适当地估计要创建的包装集合(HashMap或Multimap)的容量,以避免重复的重复。

如前所述, MultiMap是您的最佳选择。

根据您的业务要求或数据文件的约束,您可能需要考虑对其进行一次性排序,以使其更加优化以进行加载。