Java HashMap序列化和反序列化更改
我们正在使用内存数据网格(IMDG),我们有一个迁移工具。为了验证所有对象都已成功迁移,我们从序列化版本计算对象的总和 我们看到HashMap出现了一些问题,我们将其序列化,但当我们反序列化它时,校验和会发生变化。下面是一个简单的测试用例:Java HashMap序列化和反序列化更改,java,serialization,hashmap,Java,Serialization,Hashmap,我们正在使用内存数据网格(IMDG),我们有一个迁移工具。为了验证所有对象都已成功迁移,我们从序列化版本计算对象的总和 我们看到HashMap出现了一些问题,我们将其序列化,但当我们反序列化它时,校验和会发生变化。下面是一个简单的测试用例: @Test public void testMapSerialization() throws IOException, ClassNotFoundException { TestClass tc1 = new TestClass(); tc
@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如下所示:
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"));
}
}
我希望能够序列化HashMap,并在反序列化它时获得相同的校验和。你知道有没有解决办法或者我做错了什么吗
谢谢
迭戈你没有做错什么,只是用HashMap做不到。在HashMap中,顺序是不能保证的。改用a 基于哈希表的 地图界面。此实现 提供所有可选映射 操作,并允许空值 和空键。(HashMap类) 大致相当于哈希表, 除了它是不同步的和 允许空值。)此类不允许 保证地图的顺序; 特别是,它不能保证 顺序将保持不变 随着时间的推移。
来源:您的校验和不能依赖于条目的顺序,因为HashMap没有顺序。使用TreeMap的替代方法是LinkedHashMap(它保留一个顺序),但真正的解决方案是使用一个不依赖于条目顺序的哈希代码 使用一号订单的LinkedHashMap。 TreeMap未订购。树形图是一种分类图。 树映射对元素进行排序,而不考虑插入顺序
我也在考虑建议使用LinkedHashMap,但即使通过反序列化也能保证顺序吗?我想一定是。这还不是很清楚:@Sean,我不确定它是否被记录在任何地方,但我发现它确实存在。我倾向于理所当然地使用LHM,因为它倾向于使调试更容易,但我会避免依赖它的顺序进行生产。校验和取决于HashMap的序列化,显然这取决于顺序。我最终将类型更改为TreeMap,因为它还帮助我们解决了从IMDG到关系数据库的持久化过程中的其他问题。谢谢!我希望避免将其更改为另一个实现,但它最终是更好的解决方案,因为它还解决了我们在将IMDG持久化为关系数据库时遇到的一些其他问题。
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();
}
{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}