Как вставить два разных объекта по одному ключу в HashMap
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
# Вставка двух объектов по одному ключу в HashMap
Проблема и суть вопроса
В стандартной HashMap по одному ключу может храниться только одно значение. Если вы вставите второе значение с тем же ключом, оно переопределит первое:
HashMap<String, String> map = new HashMap<>();
map.put("key", "value1");
map.put("key", "value2");
System.out.println(map.get("key")); // value2 - value1 потеряно!
Это является базовым поведением HashMap. Однако есть несколько способов хранить несколько значений по одному ключу.
Решение 1: HashMap с коллекциями значений
Самое частое решение — использовать коллекцию (List, Set) в качестве значения:
// HashMap с List значений
HashMap<String, List<String>> multiMap = new HashMap<>();
// Вставка первого значения
multiMap.put("key", new ArrayList<>());
multiMap.get("key").add("value1");
// Вставка второго значения по тому же ключу
multiMap.get("key").add("value2");
System.out.println(multiMap.get("key")); // [value1, value2]
Более удобный способ с помощью computeIfAbsent:
public class MultiValueMap {
private final HashMap<String, List<String>> map = new HashMap<>();
public void put(String key, String value) {
map.computeIfAbsent(key, k -> new ArrayList<>())
.add(value);
}
public List<String> get(String key) {
return map.getOrDefault(key, Collections.emptyList());
}
public static void main(String[] args) {
MultiValueMap mm = new MultiValueMap();
mm.put("key", "value1");
mm.put("key", "value2");
System.out.println(mm.get("key")); // [value1, value2]
}
}
Решение 2: HashMap с HashSet
Если нужна уникальность значений, используем Set:
HashMap<String, Set<String>> multiMap = new HashMap<>();
multiMap.computeIfAbsent("key", k -> new HashSet<>())
.add("value1");
multiMap.computeIfAbsent("key", k -> new HashSet<>())
.add("value2");
System.out.println(multiMap.get("key")); // [value1, value2]
Решение 3: Использование Apache Commons MultiMap
Для удобства можно использовать готовую реализацию из Apache Commons Collections:
import org.apache.commons.collections4.MultiMap;
import org.apache.commons.collections4.map.MultiValueMap;
public class ApacheMultiMapExample {
public static void main(String[] args) {
MultiMap<String, String> multiMap = new MultiValueMap<>();
multiMap.put("key", "value1");
multiMap.put("key", "value2");
System.out.println(multiMap.get("key")); // [value1, value2]
}
}
Решение 4: Google Guava Multimap
Guava предоставляет несколько вариантов MultiMap:
import com.google.common.collect.Multimap;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.HashMultimap;
public class GuavaMultimapExample {
public static void main(String[] args) {
// ListMultimap - позволяет дубликаты
Multimap<String, String> listMultimap = ArrayListMultimap.create();
listMultimap.put("key", "value1");
listMultimap.put("key", "value2");
listMultimap.put("key", "value1"); // Дубликат допускается
System.out.println(listMultimap.get("key"));
// [value1, value2, value1]
// SetMultimap - уникальные значения
Multimap<String, String> setMultimap = HashMultimap.create();
setMultimap.put("key", "value1");
setMultimap.put("key", "value2");
setMultimap.put("key", "value1"); // Дубликат игнорируется
System.out.println(setMultimap.get("key"));
// [value1, value2]
}
}
Сравнение подходов
| Подход | Вес кода | Производительность | Флексибильность |
|---|---|---|---|
| HashMap<K, List<V>> | Средний | Отличная | Высокая |
| HashMap<K, Set<V>> | Средний | Отличная | Высокая |
| Apache Commons | Малый | Хорошая | Средняя |
| Google Guava | Малый | Хорошая | Высокая |
Практический пример: Логирование событий по ключу
public class EventLog {
private final Map<String, List<String>> events = new HashMap<>();
public void logEvent(String category, String event) {
events.computeIfAbsent(category, k -> new ArrayList<>())
.add(event);
}
public List<String> getEvents(String category) {
return events.getOrDefault(category, Collections.emptyList());
}
public static void main(String[] args) {
EventLog log = new EventLog();
log.logEvent("auth", "User login at 10:00");
log.logEvent("auth", "User logout at 11:00");
log.logEvent("purchase", "Item A bought");
log.logEvent("purchase", "Item B bought");
System.out.println(log.getEvents("auth"));
// [User login at 10:00, User logout at 11:00]
}
}
Важные моменты
1. Потокобезопасность — если используете в многопоточной среде:
Map<String, List<String>> syncMap =
Collections.synchronizedMap(new HashMap<>());
2. Производительность — если часто добавляете значения, используйте LinkedList вместо ArrayList на чтение происходит дольше, но insertion быстрее в начале/конце.
3. Памяти — храня коллекции в HashMap, помните о потреблении памяти.
Итого
Для вставки двух разных объектов по одному ключу:
- Стандартное решение:
HashMap<K, List<V>>сcomputeIfAbsent() - Для уникальности:
HashMap<K, Set<V>> - Готовое решение: Google Guava
Multimapили Apache CommonsMultiMap
Выбор зависит от требований и предпочтений команды. На интервью хорошо будет показать несколько вариантов и объяснить плюсы/минусы каждого.