Почему HashMap «не содержит» только те ключи, которые были изменены внутри? - PullRequest
0 голосов
/ 24 августа 2011

В моей программе у меня есть HashMap. Он имеет HashSets of Strings в качестве своих ключей и PriorityQueues of Strings в качестве своих значений. Когда я изменяю содержимое одного из его ключей, он больше не остается членом HashMap. Это кажется странным для меня, так как я не меняю ссылку на ключ. Я просто изменяю его содержание. Пожалуйста, взгляните на следующий фрагмент:

HashMap<HashSet<String>, PriorityQueue<String>> myHashMap=new HashMap<>();

HashSet<String> myHashSet=new HashSet<>();
myHashSet.add("abc");
myHashSet.add("mnq");
myHashSet.add("al;ksghl");

PriorityQueue<String> myPriorityQueue=new PriorityQueue<>();
myPriorityQueue.add("3h4");
myPriorityQueue.add("lskdjf");

myHashMap.put(myHashSet, myPriorityQueue);

if(myHashMap.containsKey(myHashSet))
    System.out.println("Yes!");

myHashSet.remove("abc");

if(myHashMap.containsKey(myHashSet))
    System.out.println("Yes!");

В принципе, я ожидаю увидеть два «Да!», Действительно, он печатает только одно. Я провел тщательную отладку и понял, что ссылочный номер для myHashSet не меняется после удаления одного из его членов. Поэтому у этой программы не должно быть причин не печатать второе «Да!».

Любая помощь очень ценится.

Ответы [ 2 ]

6 голосов
/ 24 августа 2011

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

Цитируя ,Javadoc :

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

Попробуйте добавить строку

System.out.println(myHashSet.hashCode());

до и после вызова remove, чтобы увидеть разницу.

1 голос
/ 24 августа 2011

Ключ Hashmap отключает хэш / эквивалент ключа (который был указан, меняется). Если вы заботитесь об идентичности, вы должны использовать java.util.IdentityHashMap

...