Почему у моего HashMap есть дубликат ключа?
У нас есть класс с именем Subscriber, который расширяет "HashMap". У нас есть много экземпляров этого класса в списке, и у каждого экземпляра есть набор записей, установленных на карту, один из них - "статус".
Наша программа обновляет значение "status", вызывая метод на подписчике, который просто помещает в HashMap.
Наша программа может работать несколько дней (недель) без каких-либо проблем, но иногда мы наблюдали странное поведение в некоторых других частях системы, которые используют данные из HashMap. Для нас, похоже, есть дубликат ключа в одном или нескольких экземплярах подписчика.
Нам удается создать дамп jmap, и, основываясь на дампе, он ищет, что у нас дважды установлен "статус", когда я смотрю дамп в VisualVM.
В настоящее время мы используем версию Java: 1.7.0_25 (Oracle)
Как это возможно? Или я неправильно читаю VisualVM?
1 ответ
Помимо проблемы с потоками, существует четкий путь к этому результату:
class Key implements CharSequence {
private byte[] key;
public Key(String key) {
// Take a copy of the bytes of the string.
this.key = key.getBytes();
}
@Override
public int length() {
return key.length;
}
@Override
public char charAt(int index) {
return (char) key[index];
}
@Override
public CharSequence subSequence(int start, int end) {
return new Key(new String(key).substring(start, end));
}
// Allow the key to change.
public void setKey(String newValue) {
key = newValue.getBytes();
}
@Override
public String toString() {
return new String(key);
}
}
public void test() {
Map<CharSequence, String> testMap = new HashMap<>();
Key aKey = new Key("a");
Key bKey = new Key("b");
testMap.put(aKey, "a");
testMap.put(bKey, "b");
bKey.setKey("a");
System.out.println(testMap.keySet());
}
По сути, это делает ключи карты изменяемыми, чтобы их можно было изменить после добавления на карту.
Хотя это может и не быть проблемой, с которой вы сталкиваетесь (проблема многопоточности гораздо более вероятна), это реальный ответ на вопрос. Почему у моего HashMap есть дубликат ключа?,