HashMap la sérialisation et la désérialisation des changements
Nous travaillons avec une mémoire de données de la grille (IMDG) et nous disposons d'un outil de migration. Afin de vérifier que tous les objets sont migrés avec succès, nous calculons la chucksum les objets à partir de sa version sérialisée.
Nous assistons à quelques problèmes avec la table de hachage, où nous sérialiser, mais quand nous le désérialiser la somme de contrôle des changements. Voici un test simple cas:
@Test
public void testMapSerialization() throws IOException, ClassNotFoundException {
TestClass tc1 = new TestClass();
tc1.init();
String checksum1 = SpaceObjectUtils.calculateChecksum(tc1);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutput out = null;
byte[] objBytes = null;
out = new ObjectOutputStream(bos);
out.writeObject(tc1);
objBytes = bos.toByteArray();
out.close();
ByteArrayInputStream bis = new ByteArrayInputStream(objBytes);
ObjectInputStream in = new ObjectInputStream(bis);
TestClass tc2 = (TestClass) in.readObject();
String checksum2 = SpaceObjectUtils.calculateChecksum(tc2);
assertEquals(checksum1, checksum2);
}
TestClass ressemble à ceci:
class TestClass implements Serializable {
private static final long serialVersionUID = 5528034467300853270L;
private Map<String, Object> map;
public TestClass() {
}
public Map<String, Object> getMap() {
return map;
}
public void setMap(Map<String, Object> map) {
this.map = map;
}
public void init() {
map = new HashMap<String, Object>();
map.put("name", Integer.valueOf(4));
map.put("type", Integer.valueOf(4));
map.put("emails", new BigDecimal("43.3"));
map.put("theme", "sdfsd");
map.put("notes", Integer.valueOf(4));
map.put("addresses", Integer.valueOf(4));
map.put("additionalInformation", new BigDecimal("43.3"));
map.put("accessKey", "sdfsd");
map.put("accountId", Integer.valueOf(4));
map.put("password", Integer.valueOf(4));
map.put("domain", new BigDecimal("43.3"));
}
}
Et c'est la méthode pour calculer la somme de contrôle:
public static String calculateChecksum(Serializable obj) {
if (obj == null) {
throw new IllegalArgumentException("The object cannot be null");
}
MessageDigest digest = null;
try {
digest = MessageDigest.getInstance("MD5");
} catch (java.security.NoSuchAlgorithmException nsae) {
throw new IllegalStateException("Algorithm MD5 is not present", nsae);
}
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutput out = null;
byte[] objBytes = null;
try {
out = new ObjectOutputStream(bos);
out.writeObject(obj);
objBytes = bos.toByteArray();
out.close();
} catch (IOException e) {
throw new IllegalStateException(
"There was a problem trying to get the byte stream of this object: " + obj.toString());
}
digest.update(objBytes);
byte[] hash = digest.digest();
StringBuilder hexString = new StringBuilder();
for (int i = 0; i < hash.length; i++) {
String hex = Integer.toHexString(0xFF & hash[i]);
if (hex.length() == 1) {
hexString.append('0');
}
hexString.append(hex);
}
return hexString.toString();
}
Si vous imprimez les cartes de tc1 et tc2, vous pouvez voir que les éléments ne sont pas dans le même lieu:
{accessKey=sdfsd, accountId=4, theme=sdfsd, name=4, domain=43.3, additionalInformation=43.3, emails=43.3, addresses=4, notes=4, type=4, password=4}
{accessKey=sdfsd, accountId=4, name=4, theme=sdfsd, domain=43.3, emails=43.3, additionalInformation=43.3, type=4, notes=4, addresses=4, password=4}
Je voudrais être en mesure de sérialiser la table de hachage et d'obtenir la même somme quand je désérialiser. Savez-vous si il existe une solution ou si je fais quelque chose de mal?
Merci!
Diego
OriginalL'auteur dgaviola | 2011-05-13
Vous devez vous connecter pour publier un commentaire.
Vous ne faites rien de mal, il ne peut tout simplement pas être fait avec une table de hachage. Dans une table de hachage, l'ordre n'est pas garanti. Utiliser un
TreeMap
à la place.Source:
Hashmap
OriginalL'auteur Sean Patrick Floyd
Votre somme de contrôle ne peut pas dépendre de l'ordre des entrées comme table de hachage n'est pas ordonné. Une alternative à l'utilisation de TreeMap est LinkedHashMap (qui conserve un ordre), mais la vraie solution est d'utiliser un hashCode qui n'est pas selon l'ordre des inscriptions.
Je ne suis pas sûr que c'est documenté nulle part, mais j'ai trouvé que c'était. J'ai tendance à utiliser LHM comme une question de cours, car il a tendance à faire un débogage plus facile, mais je voudrais éviter de compter sur son ordre, à des fins de production.
La somme de contrôle dépend de la sérialisation de la table de hachage et, apparemment, qui dépend de l'ordre. J'ai fini par changer le type de TreeMap, car il nous a aussi aidé à résoudre d'autres problèmes lors de la persistance de l'IMDG pour une base de données relationnelle.
OriginalL'auteur Peter Lawrey
OriginalL'auteur AmitG