Могу ли я иметь HashSets в качестве ключей в HashMap? Предложите альтернативу, если нет - PullRequest
5 голосов
/ 19 марта 2012

Редактировать: теперь правильно объяснил проблему.

У меня есть хэш-карта, где я хочу хранить наборы слов, видимых вместе (ключ), и строки, в которых они были видны вместе (значение).Это структура, которую я придумал:

HashMap<HashSet<String>, HashSet<Integer>> hm= ...

для входных данных:

  1. манго, банан, яблоко

  2. яблоко, банан

  3. персик, морж

  4. морж, персик

Пока я это читаю,построчно я создаю новые временные ключи (хэш-наборы, еще не вставленные в хэш-карту) из комбинации слов в строке.Каждый временный ключ является хэш-набором поднабора слов в строке.Если в моем hashmap уже существует временный ключ, который я проверяю с помощью

if(hashmap.containsKey(hashset))

, я просто добавляю новую строку к соответствующему значению этого ключа, если нет, я делаю новую запись в hashmap и заботлюсь оэто.

Ни в коем случае я не могу изменить существующий ключ.Я только обновляю их соответствующие значения в hasmmap.

мой hashmap в конце чтения файла должен выглядеть примерно так

[apple, banana] = [1,2]

[персик, морж] = [3,4]

...

проблема в том, что

if(hashmap.containsKey(hashset))

кусок кода не 'всегда обнаруживать существующие ключи.Почему это?Разрешена эта структура?

Спасибо

Ответы [ 3 ]

7 голосов
/ 19 марта 2012

Это должно работать, но вам нужно следить за изменчивостью ключей. Если вы когда-нибудь измените содержимое одного из ключей, его хеш-код изменится, и ваша карта начнет делать странные вещи. Из Javadoc для Map:

Примечание: следует соблюдать особую осторожность, если в качестве карты используются изменяемые объекты. ключи. Поведение карты не указывается, если значение объекта изменяется таким образом, что влияет на сравнения равных в то время как Объект является ключом на карте. Особый случай этого запрета заключается в том, что недопустимо, чтобы карта содержала себя в качестве ключа. Пока это допустимо, чтобы карта содержала себя как значение, крайняя осторожность рекомендуется: методы equals и hashCode более не определены на такой карте.

Чтобы избежать этого, оберните ключи Collections.unmodifiableSet() сразу после создания или просто используйте ImmutableSet из Гуавы.

4 голосов
/ 19 марта 2012

Вы можете, но как только вы добавили HashSet в качестве ключа к HashMap, вы не должны изменять его снова, так как HashSet.hashCode() может измениться, и вы никогда не найдете свой HashSet снова. Другими словами, если вы делаете что-то подобное, убедитесь, что ваши ключи неизменны HashSets (см. Также ответ Мэтта здесь )

Альтернативой является использование MultiKeyMap вместе с MultiKey из общих коллекций

1 голос
/ 19 марта 2012

Проблема, с которой вы столкнулись, хорошо объяснена @Lukas ans @ Matt.
Я думаю, вы могли бы обойтись, используя расширение или шаблон декоратора для создания Hashset, который пересекает equals и hashCode вспособ, который не зависит от содержимого.

Таким образом, вы можете избежать введения зависимостей от сторонних jar-файлов только для конкретной проблемы

...