Java 创建arraylist的hashmap的最佳方法

Java 创建arraylist的hashmap的最佳方法,java,data-structures,collections,arraylist,hashmap,Java,Data Structures,Collections,Arraylist,Hashmap,我有一百万行.txt格式的数据。格式很简单。对于每行: user1,value1 user2,value2 user3,value3 user1,value4 ... user1,value1 user2,value2 user3,value3 user1,value4 ... 你知道我的意思。对于每个用户,它可能会出现很多次,或者只出现一次(你永远不知道)。我需要找出每个用户的所有值。因为用户可能随机出现,所以我使用Hashmap来实现。即:HashMap(key:String,value:A

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

user1,value1 user2,value2 user3,value3 user1,value4 ... user1,value1 user2,value2 user3,value3 user1,value4 ...
你知道我的意思。对于每个用户,它可能会出现很多次,或者只出现一次(你永远不知道)。我需要找出每个用户的所有值。因为用户可能随机出现,所以我使用Hashmap来实现。即:HashMap(key:String,value:ArrayList)。但要向arrayList添加数据,我必须不断使用HashMap get(key)来获取arrayList,向其添加值,然后将其放回HashMap。我觉得效率不是很高。有人知道更好的方法吗

如果使用LinkedList而不是ArrayList,速度会更快,因为ArrayList在接近容量时需要调整大小


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

使用谷歌收藏中的多重地图。它允许同一个键有多个值


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

我认为您需要的是多重映射。您可以从apache的commons集合或google集合中获得它

“收集类似于地图,但 它可以关联多个值 只需一个键。如果调用put(K, 五) 两次,用同一把钥匙,但是 不同的值,多重映射 包含从键到两者的映射 价值观。”


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

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

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

[value4, value1]
[value2]
[value3]

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


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

< P>我找不到任何简单的方法。“多重贴图”并不总是可用的选项。所以我写了一些东西

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;
    }
}
公共类上下文扩展HashMap{
public V addMulti(K参数,V参数){
V值=get(参数K);
如果(值==null){
列表=新的ArrayList();
列表。添加(paramV);
put(paramK,paramV);
}else if(列表的值实例){
((列表)值)。添加(paramV);
}否则{
列表=新的ArrayList();
列表。添加(值);
列表。添加(paramV);
put(参数,(V)列表);
}
返回参数v;
}
}

如果您不想导入库

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;    
    }    
  }    
}    
package-util;
导入java.util.ArrayList;
导入java.util.HashMap;
导入java.util.List;
/**    
*多重映射的简单实现。此实现允许在中复制元素
*价值观。(我知道像这样的课程还有很多,但我能上的那些课程不起作用)。
*/    
公共类多重映射扩展HashMap{
/**    
*查找映射到给定键的列表。如果没有,则创建一个新的列表
*映射并向其添加了值。
*     
*@param-key
*@param值
*@如果已创建列表,则返回true;如果创建新列表,则返回false。
*/    
公共布尔putOne(K键,V值){
如果(this.containsKey(key)){
this.get(key).add(value);
返回true;
}否则{
列表值=新的ArrayList();
增加(价值);
这个.put(键、值);
返回false;
}    
}    
}    

自Java 8以来,您可以使用
map.computeIfAbsent

Collection values=map.computeIfAbsent(用户,k->new ArrayList());
增加(价值);

其他答案都是正确的。我只是不想使用外部库。ArrayList几乎肯定会有更好的平均性能,即使调整大小也是如此。当您希望所有操作的时间大致相同时,LinkedList是一个不错的选择,例如,它们涉及到UI中,您不希望用户执行操作时出现随机延迟。这应该是一个注释
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;
    }
}
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;    
    }    
  }    
}    
Collection<String> values = map.computeIfAbsent(user, k -> new ArrayList<>());
values.add(value);