Подтвердить что ты не робот

Лучший способ создать хэш-карту arraylist

У меня есть миллион строк данных в формате .txt. формат очень прост. Для каждой строки:

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

Вы знаете, что я имею в виду. Для каждого пользователя он может появляться много раз или появляться только один раз (вы никогда не знаете). Мне нужно узнать все значения для каждого пользователя. Поскольку пользователь может отображаться случайным образом, я использовал Hashmap для этого. То есть: HashMap (ключ: String, значение: ArrayList). Но для добавления данных в массивList, я должен постоянно использовать HashMap get (key), чтобы получить массивList, добавить значение к нему, а затем вернуть его в HashMap. Я чувствую, что это не так эффективно. Кто-нибудь знает лучший способ сделать это?

4b9b3361

Ответ 1

Вам не нужно повторно добавлять ArrayList на свою карту. Если ArrayList уже существует, просто добавьте к нему свое значение.

Улучшенная реализация может выглядеть так:

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

при обработке каждой строки:

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

Последующий отчет за апрель 2014 года. Я написал исходный ответ еще в 2009 году, когда мои знания о Гуаве были ограничены. В свете всего, что делает Google Guava, теперь я рекомендую использовать его Multimap, а не изобретать его.

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

Выходы:

[value4, value1]
[value2]
[value3]

Ответ 3

Значения ArrayList в вашем HashMap являются ссылками. Вам не нужно "возвращать его в HashMap". Вы работаете над объектом, который уже существует как значение в HashMap.

Ответ 4

Если вы не хотите импортировать библиотеку.

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

Ответ 5

Я думаю, что вы хотите, это Multimap. Вы можете получить его из коллекции коллекций apache или google-коллекций.

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

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

", подобный карте, но которые могут связывать несколько значений с одним ключом. Если вы вызываете put (K, V) дважды, с тем же ключом, но разные значения, мультимап содержит сопоставления от ключа к обеим значения".

Ответ 6

Я не мог найти простой способ. MultiMap не всегда доступен. Поэтому я написал что-то такое.

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

Ответ 8

это будет быстрее, если вы использовали LinkedList вместо ArrayList, так как ArrayList потребуется изменить размер, когда он приближается к емкости.

вы также захотите соответствующим образом оценить емкость собранной коллекции (HashMap или Multimap), которую вы создаете, чтобы избежать повторного повторного перехвата.

Ответ 9

Как уже упоминалось, MultiMap - ваш лучший вариант.

В зависимости от ваших бизнес-требований или ограничений в файле данных вы можете захотеть сделать одноразовую сортировку, чтобы сделать ее более оптимизированной для загрузки.