问题描述
我打算序列化和反序列化键为字符串的哈希映射.
I am intending to serialize and deserialize a hashmap whose key is a string.
根据Josh Bloch的Effective Java,我了解以下内容.P.222
From Josh Bloch's Effective Java, I understand the following.P.222
我的问题是:1)通常,映射的键类的重载equals和哈希码可以解决此问题,并且可以正确还原映射吗?
My questions are:1) In general, would overriding equals and hashcode of the key class of the map resolve this issue and the map can be correctly restored?
2)如果我的键是一个String,并且String类已经覆盖了hashCode()方法,我仍然会遇到上述问题.(我看到一个错误,使我认为这可能仍然是一个问题,即使键是具有覆盖hashCode的String.)
2) If my key is a String and the String class is already overriding the hashCode() method, would I still have problem described above.(I am seeing a bug which makes me think this is probably still a problem even though the key is String with overriding hashCode.)
3)以前,我是通过序列化一系列条目(键,值)来解决此问题的,当反序列化时,我将重建映射.我想知道是否有更好的方法.
3)Previously, I got around this issue by serializing an array of entries (key, value) and when deserializing I would reconstruct the map. I am wondering if there is a better approach.
4)如果对问题1和2的回答仍然不能保证,有人可以解释为什么吗?如果hashCode相同,它们是否会跨JVM进入相同的存储桶?
4) If the answers to question 1 and 2 are that it still can't be guaranteed, could someone explain why? If the hashCodes are the same would they go to the same buckets across JVMs?
谢谢,恩典
推荐答案
java.util.HashMap
的序列化形式不会序列化存储桶本身,并且哈希码不属于持久状态.来自javadocs:
The serialization form of java.util.HashMap
doesn't serialize the buckets themselves, and the hash code is not part of the persisted state. From the javadocs:
来自 http://java.sun.com/j2se/1.5.0/docs/api/serialized-form.html#java.util.HashMap
持久状态基本上包括键和值以及一些内部管理.反序列化后,哈希图将完全重建;钥匙被重新整理并放置在适当的存储桶中.
The persisted state basically comprises the keys and values and some housekeeping. When deserialized, the hashmap is completely rebuilt; the keys are rehashed and placed in appropriate buckets.
因此,添加String键应该可以正常工作.我猜你的错误在其他地方.
So, adding String keys should work just fine. I would guess your bug lies elsewhere.
这是一个junit 4测试用例,用于对地图进行序列化和反序列化,并且minics VM更改哈希码.尽管哈希序列在反序列化后有所不同,但测试仍通过.
Here's a junit 4 test case that serializes and deserializes a map, and minics VMs changing hashcodes. The test passes, despite the hashcodes being different after deserialization.
import org.junit.Assert;
import org.junit.Test;
import java.io.*;
import java.util.HashMap;
public class HashMapTest
{
@Test
public void testHashMapSerialization() throws IOException, ClassNotFoundException
{
HashMap map = new HashMap();
map.put(new Key("abc"), 1);
map.put(new Key("def"), 2);
ByteArrayOutputStream out = new ByteArrayOutputStream();
ObjectOutputStream objOut = new ObjectOutputStream(out);
objOut.writeObject(map);
objOut.close();
Key.xor = 0x7555AAAA; // make the hashcodes different
ObjectInputStream objIn = new ObjectInputStream(new ByteArrayInputStream(out.toByteArray()));
HashMap actual = (HashMap) objIn.readObject();
// now try to get a value
Assert.assertEquals(2, actual.get(new Key("def")));
}
static class Key implements Serializable
{
private String keyString;
static int xor = 0;
Key(String keyString)
{
this.keyString = keyString;
}
@Override
public int hashCode()
{
return keyString.hashCode()^xor;
}
@Override
public boolean equals(Object obj)
{
Key otherKey = (Key) obj;
return keyString.equals(otherKey.keyString);
}
}
}
这篇关于使用键作为字符串对地图进行序列化和反序列化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!