Вопрос-ответ

HashMap with multiple values under the same key

Хэш-карта с несколькими значениями под одним ключом

Возможно ли реализовать HashMap с одним ключом и двумя значениями?
Так же, как HashMap<userId, ClientID,timeStamp>?

Если нет, есть ли какой-либо другой способ реализовать хранение нескольких значений, например, одного ключа и двух значений?

Переведено автоматически
Ответ 1

Вы могли бы:


  1. Используйте карту, которая имеет список в качестве значения. Map<KeyType, List<ValueType>>.

  2. Создайте новый класс-оболочку и разместите экземпляры этой оболочки на карте. Map<KeyType, WrapperType>.

  3. Используйте класс, подобный кортежу (позволяет не создавать множество оберток). Map<KeyType, Tuple<Value1Type, Value2Type>>.

  4. Используйте несколько карт параллельно.


Примеры

1. Карта со списком в качестве значения

// create our map
Map<String, List<Person>> peopleByForename = new HashMap<>();

// populate it
List<Person> people = new ArrayList<>();
people.add(new Person("Bob Smith"));
people.add(new Person("Bob Jones"));
peopleByForename.put("Bob", people);

// read from it
List<Person> bobs = peopleByForename["Bob"];
Person bob1 = bobs[0];
Person bob2 = bobs[1];

Недостатком этого подхода является то, что список не привязан ровно к двум значениям.

2. Использование класса-оболочки

// define our wrapper
class Wrapper {
public Wrapper(Person person1, Person person2) {
this.person1 = person1;
this.person2 = person2;
}

public Person getPerson1() { return this.person1; }
public Person getPerson2() { return this.person2; }

private Person person1;
private Person person2;
}

// create our map
Map<String, Wrapper> peopleByForename = new HashMap<>();

// populate it
peopleByForename.put("Bob", new Wrapper(new Person("Bob Smith"),
new Person("Bob Jones"));

// read from it
Wrapper bobs = peopleByForename.get("Bob");
Person bob1 = bobs.getPerson1();
Person bob2 = bobs.getPerson2();

Недостатком этого подхода является то, что вам приходится писать много стандартного кода для всех этих очень простых контейнерных классов.

3. Использование кортежа

// you'll have to write or download a Tuple class in Java, (.NET ships with one)

// create our map
Map<String, Tuple2<Person, Person> peopleByForename = new HashMap<>();

// populate it
peopleByForename.put("Bob", new Tuple2(new Person("Bob Smith",
new Person("Bob Jones"));

// read from it
Tuple<Person, Person> bobs = peopleByForename["Bob"];
Person bob1 = bobs.Item1;
Person bob2 = bobs.Item2;

На мой взгляд, это лучшее решение.

4. Несколько карт

// create our maps
Map<String, Person> firstPersonByForename = new HashMap<>();
Map<String, Person> secondPersonByForename = new HashMap<>();

// populate them
firstPersonByForename.put("Bob", new Person("Bob Smith"));
secondPersonByForename.put("Bob", new Person("Bob Jones"));

// read from them
Person bob1 = firstPersonByForename["Bob"];
Person bob2 = secondPersonByForename["Bob"];

Недостатком этого решения является то, что не очевидно, что две карты связаны, программная ошибка может привести к рассинхронизации двух карт.

Ответ 2

Нет, не просто как HashMap. В основном вам понадобится HashMap из ключа в набор значений.

Если вы предпочитаете использовать внешние библиотеки, Guava использует именно эту концепцию в Multimap реализациях, таких как ArrayListMultimap, HashMultimap, LinkedHashMultimap и т.д.

Multimap<String, Integer> nameToNumbers = HashMultimap.create();

System.out.println(nameToNumbers.put("Ann", 5)); // true
System.out.println(nameToNumbers.put("Ann", 5)); // false
nameToNumbers.put("Ann", 6);
nameToNumbers.put("Sam", 7);

System.out.println(nameToNumbers.size()); // 3
System.out.println(nameToNumbers.keySet().size()); // 2
Ответ 3

Еще один хороший выбор - использовать MultivaluedMap из Apache Commons. Взгляните на Все известные реализующие классы в верхней части страницы для специализированных реализаций.

Пример:

HashMap<K, ArrayList<String>> map = new HashMap<K, ArrayList<String>>()

может быть заменен на

MultiValuedMap<K, String> map = new MultiValuedHashMap<K, String>();

Итак,

map.put(key, "A");
map.put(key, "B");
map.put(key, "C");

Collection<String> coll = map.get(key);

приведет к получению коллекцииcoll, содержащей "A", "B" и "C".

Ответ 4

Взгляните на Multimap из guava-библиотек и ее реализацию - HashMultimap


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


java list