Java, как определить, изменилась ли хэш-карта через некоторое время или операции?

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

Я могу сделать

String firstState = map.toString();

тогда

String secondState = map.toString();

а затем сравнить, являются ли они равными?

EDIT: по состоянию я имею в виду что-то, что изменится, если что-нибудь изменится в HashMap

4 ответа

Единственный способ узнать, действительно ли что-то изменилось, - это сделать копию карты и сравнить ее с картой в более позднее время:

HashMap<string, string=""> m = new HashMap<>();
// Populate map...
// Save the state:
HashMap<string, string=""> saved = new HashMap<>(m);
// Clients might modify map here...
// Test if the map was modified:
boolean modified = saved.equals(m);
</string,></string,>

HashMap.hashCode() может быть использован только сказать, если карта так изменилась (если изменения Hashcode). Если хеш-код не изменяется, это не гарантирует, что карта не была изменена.

Кроме того, обернуть карту и переопределить методы put() и clear() также недостаточно, потому что если кто-то изменит значение с помощью put(), возможно, что позже он снова вызовет put() и установит старое значение, которое вы больше не хранятся и не могут определить, восстанавливается ли прежнее старое значение.

Неправильное использование метода на основе hascode:

Если карта содержит String как значения, например, мы можем изменить значение на другую String имеющую тот же самый хэш-код, так что HashMap.hashCode() не изменится.

Например, следующие String имеют одинаковый хэш-код, но они не равны:

String s1 = ""; // Hashcode = 0
String s2 = "\0"; // Hashcode = 0
String s3 = "\0\0"; // Hashcode = 0
HashMap<string, string=""> m = new HashMap<>();
m.put("one", s1);
m.put("one", s2); // This does not change m.hashCode() yet its content changes!
</string,>

Неправильное использование метода на основе обертки:

HashMap<string, string=""> m = new HashMap<>();
m.put("one", "1");
// Now "save" state and modify the map via a wrapper
Map<string, string=""> w = ...; // Create a wrapper
w.put("one", "2"); // This will trigger that map is modified
w.put("one", "1"); // This will trigger that map is modified, yet it is restored
// Now the contents of the map is identical to the state that was saved.
</string,></string,>


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

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

Но в ответе на вопрос, я думаю, есть один важный аспект для рассмотрения - количество ключей. Если ключей не слишком много, метод "copy construction + equals" будет хорошей альтернативой решению на основе обертки. (сначала сделайте и скопируйте копию, а затем сравните ее с текущим состоянием карты). Но если слишком много ключей, две операции могут повлечь большие накладные расходы.


Вы можете сравнить его "хэш-значения"

int hash1 = map.hashCode();
// do something
int hash2 = map.hashCode();

JavaDoc заявляет:

<blockquote>

Хэш-код карты определяется как сумма хеш-кодов каждой записи в представлении карты entrySet()


Вы можете сделать копию карты.

HashMap old = new HashMap(map);

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

if (!old.equals(map)) { System.out.println("Something changed");
}

licensed under cc by-sa 3.0 with attribution.