Лучший способ создать хэш-карту массива
-
06-07-2019 - |
Вопрос
У меня есть миллион строк данных в формате .txt.формат очень простой.Для каждой строки:
user1,value1 user2,value2 user3,value3 user1,value4 ...
Если вы понимаете, о чем я.Для каждого пользователя оно могло появиться много раз или появиться только один раз (мало ли).Мне нужно узнать все значения для каждого пользователя.Поскольку пользователь может появляться случайным образом, я использовал для этого Hashmap.То есть:HashMap (ключ:Строковое значение:список массивов).Но чтобы добавить данные в arrayList, мне приходится постоянно использовать HashMap get(key), чтобы получить arrayList, добавить к нему значение, а затем вернуть его в HashMap.Мне кажется, это не очень эффективно.Кто-нибудь знает лучший способ сделать это?
Решение
Вам не нужно повторно добавлять 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 были ограничены.В свете всего того, что делает 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]
Другие советы
Используйте Multimap из Google Collections. Позволяет использовать несколько значений для одного и того же ключа.
https: / /google.github.io/guava/releases/19.0/api/docs/com/google/common/collect/Multimap.html р>
Значения ArrayList в вашей HashMap являются ссылками. Вам не нужно «возвращать его обратно в 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<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;
}
}
}
Начиная с Java 8
вы можете использовать map.computeIfAbsent
Collection<String> values = map.computeIfAbsent(user, k -> new ArrayList<>());
values.add(value);
Я думаю, что вы хотите, это Multimap. Вы можете получить его из коллекции Apache Commons или из Google-коллекций.
Я не мог найти легкий путь. 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;
}
}
было бы быстрее, если бы вы использовали LinkedList вместо ArrayList, поскольку ArrayList необходимо будет изменить размер, когда он приблизится к емкости.
вы также захотите надлежащим образом оценить емкость коллекции оберток (HashMap или Multimap), которую вы создаете, чтобы избежать повторной перефразировки. Р>
Как уже упоминалось, MultiMap
- ваш лучший вариант.
В зависимости от ваших бизнес-требований или ограничений на файл данных, вы можете рассмотреть возможность одноразовой сортировки, чтобы сделать его более оптимизированным для загрузки.