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

Многозначная хэш-таблица в Java

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

4b9b3361

Ответ 1

Нет. Такого рода идея хэш-таблиц.

Однако вы можете либо свернуть свой собственный с помощью Map<YourKeyObject, List<YourValueObject>>, либо некоторых методов утилиты для создания списка, если он отсутствует, или использовать что-то вроде Multimap из Коллекции Google.

Пример:

String key = "hello";
Multimap<String, Integer> myMap = HashMultimap.create();
myMap.put(key, 1);
myMap.put(key, 5000);
System.out.println(myMap.get(key)); // prints either "[1, 5000]" or "[5000, 1]"
myMap = ArrayListMultimap.create();
myMap.put(key, 1);
myMap.put(key, 5000);
System.out.println(myMap.get(key)); // always prints "[1, 5000]"

Обратите внимание, что Multimap не является точным эквивалентом домашнего решения; Hashtable синхронизирует все его методы, а Multimap не дает такой гарантии. Это означает, что использование Multimap может вызвать проблемы, если вы используете его для нескольких потоков. Если ваша карта используется только в одном потоке, это не будет иметь никакого значения (и вы должны использовать HashMap вместо Hashtable в любом случае).

Ответ 2

Значения хэш-таблицы - это объект, поэтому вы можете сохранить список

Ответ 3

Вместо того, чтобы дать еще один ответ на многократную передачу, я спрошу, почему вы хотите это сделать?

Связаны ли множественные значения? Если да, то, вероятно, лучше создать структуру данных для их хранения. Если нет, то, возможно, более целесообразно использовать отдельные карты.

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

Ответ 4

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

В Java класс Hashtable принимает одно значение для одного ключа. Ниже приведен пример попытки связать несколько значений с одним ключом:

Hashtable<String, String> ht = new Hashtable<String, String>();

ht.put("Answer", "42");
ht.put("Hello", "World");    // First value association for "Hello" key.
ht.put("Hello", "Mom");      // Second value association for "Hello" key.

for (Map.Entry<String, String> e : ht.entrySet()) {
  System.out.println(e);
}

В попытке включить несколько значений ("World", "Mom") в один ключ ("Hello") мы получим следующий результат для печати записей в Hashtable:

Answer=42
Hello=Mom

Пара ключей/значений "Hello" и "World" не находится в Hashtable - только вторая запись "Hello" и "Mom" находится в Hashtable. Это показывает, что нельзя иметь несколько значений, связанных с одним ключом в Hashtable.


Здесь действительно нужен multimap, который позволяет связывать несколько значений с одним ключом.

Одна реализация мультимапа Multimap из Коллекции Google:

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

mm.put("Answer", "42");
mm.put("Hello", "World");
mm.put("Hello", "Mom");

for (Map.Entry<String, String> e : mm.entries()) {
  System.out.println(e);
}

Это похоже на приведенный выше пример, который использовал Hashtable, но поведение совсем другое - a Multimap позволяет связывать несколько значений с одним ключом. Результатом выполнения вышеуказанного кода является следующее:

Answer=42
Hello=Mom
Hello=World

Как видно, для ключа "Hello" связаны значения "Mom" и "World". В отличие от Hashtable, он не отбрасывает одно из значений и не заменяет его другим. Multimap способен удерживать несколько значений для каждой клавиши.

Ответ 5

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

Коллекции Google (обновление: Guava) библиотека содержит одну реализацию, и, вероятно, ваш лучший выбор.

Изменить: конечно, вы можете сделать как Эрик предлагает, и сохраните коллекцию как ценность в вашей Hashtable (или карте, больше как правило), но это означает, что вы сами пишете ненужный код шаблона. При использовании библиотеки, такой как Google Collections, она будет заботиться о низкоуровневой "сантехнике" для вас. Ознакомьтесь с этим хорошим примером о том, как ваш код будет упрощен, используя Multimap вместо ванильных классов Java Collections.

Ответ 6

Ни один из ответов не указал, что я сделаю в первую очередь.

Самый большой прыжок, который я когда-либо делал в своих способностях OO, заключался в том, когда я решил ВСЕГДА сделать еще один класс, когда казалось, что он может быть даже немного полезен - и это одна из вещей, которые я узнал из этого шаблона.

Почти все время я обнаруживаю, что между объектами, которые я пытаюсь помещать в хэш-таблицу, существует связь. Чаще всего, есть место для класса - даже метод или два.

На самом деле, я часто обнаруживаю, что мне даже не нужна структура типа HashMap - простой HashSet отлично работает.

Элемент, который вы храните в качестве первичного ключа, может стать идентификатором нового объекта, поэтому вы можете создавать методы равенства и хэша, которые ссылаются только на один объект (eclipse может легко сделать ваши методы равенства и хэша). таким образом новый объект будет сохранять, сортировать и извлекать точно так же, как и ваш оригинал, а затем использовать свойства для хранения остальных элементов.

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

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

Ответ 7

Просто сделай сам:

Map<Object, List<Object>> multiMap = new HashMap<Object, List<Object>>();

Чтобы добавить:

  public void add(String key, Object o) {
    List<Object> list;
    if (multiMap.containsKey(key)) {
      list = multiMap.get(key);
      list.add(o);
    } else {
      list = new ArrayList<Object>();
      list.add(o);
      multiMap.put(key, list);
    }
  }

Ответ 8

См. Библиотека коллекций Google для мультикадров и подобных подобных коллекций. Встроенные коллекции не имеют прямой поддержки для этого.

Ответ 9

Что вы ищете, это Multimap. google collections api обеспечивает хорошую реализацию этого и многое другое, которое стоит изучить. Очень рекомендуется!

Ответ 10

Вам нужно использовать что-то, называемое MultiMap. Это не строго карта, но это другой API. Это примерно то же самое, что и Map < K, List <V> gt;, но у вас не будет таких методов, как entrySet() или values ​​().

Ответ 11

Simple. Вместо Hashtable<Key, Value>, используйте Hashtable<Key, Vector<Value>>.

Ответ 13

Следующий код без библиотеки Google Guava. Он используется для двойного значения в качестве ключа и отсортированного порядка

Map<Double,List<Object>> multiMap = new TreeMap<Double,List<Object>>();

for( int i= 0;i<15;i++)
{
    List<Object> myClassList = multiMap.get((double)i);
    if(myClassList == null)
    {
        myClassList = new ArrayList<Object>();
        multiMap.put((double) i,myClassList);
    }
    myClassList.add("Value "+ i);
}

List<Object> myClassList = multiMap.get((double)0);
if(myClassList == null)
{
    myClassList = new ArrayList<Object>();
    multiMap.put( (double) 0,myClassList);
}
myClassList.add("Value Duplicate");
for (Map.Entry entry : multiMap.entrySet()) 
{
  System.out.println("Key = " + entry.getKey() + ", Value = " +entry.getValue());
}