HashMap序列化和反序列化更改

dga*_*ola 5 java serialization hashmap

我们正在使用内存数据网格(IMDG),并且有一个迁移工具。为了验证是否成功迁移了所有对象,我们从其序列化版本计算对象的chucksum。

我们看到了HashMap的一些问题,我们在其中进行了序列化,但是当我们对其进行反序列化时,校验和发生了变化。这是一个简单的测试用例:

@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);
}
Run Code Online (Sandbox Code Playgroud)

TestClass看起来像这样:

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"));
    }
}
Run Code Online (Sandbox Code Playgroud)

这是计算校验和的方法:

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();
}
Run Code Online (Sandbox Code Playgroud)

如果打印tc1和tc2的地图,则可以看到元素不在同一位置:

{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}
Run Code Online (Sandbox Code Playgroud)

我希望能够序列化HashMap并在反序列化时获得相同的校验和。您知道是否有解决方案,或者我做错了什么?

谢谢!

地亚哥

Sea*_*oyd 4

你没有做错什么,只是 HashMap 无法做到这一点。在 HashMap 中,不保证顺序。使用 aTreeMap代替。

基于哈希表的 Map 接口实现。此实现提供了所有可选的映射操作,并允许空值和空键。(HashMap 类大致相当于 Hashtable,只不过它是不同步的并且允许 null。)该类不保证映射的顺序;特别是,它不保证顺序随着时间的推移保持不变。

来源: Hashmap