我打算序列化和反序列化其键为字符串的哈希图。
从Josh Bloch的Effective Java中,我了解以下内容。
P.222
我的问题是:
1)总的来说,覆盖重载的equals和映射的键类的哈希码可以解决此问题,并且可以正确还原映射吗?
2)如果我的键是一个String,并且String类已经覆盖了hashCode()方法,我仍然会遇到上述问题。
(我看到一个错误,使我认为这可能仍然是一个问题,即使键是具有覆盖hashCode的String。)
3)以前,我是通过序列化一系列条目(键,值)来解决此问题的,当反序列化时,我将重建映射。我想知道是否有更好的方法。
4)如果对问题1和2的回答仍然不能保证,有人可以解释为什么吗?如果hashCodes相同,它们是否会跨JVM进入相同的存储桶?
谢谢,格雷斯
最佳答案
java.util.HashMap
的序列化形式不会对存储桶本身进行序列化,并且哈希码也不是持久状态的一部分。从javadocs:
来自http://java.sun.com/j2se/1.5.0/docs/api/serialized-form.html#java.util.HashMap
持久状态基本上包括键和值以及一些内部管理。反序列化后,哈希图将完全重建; key 被重新整理并放置在适当的桶中。
因此,添加String键应该可以正常工作。我猜你的错误在别处。
编辑:这是一个junit 4测试用例,用于对 map 进行序列化和反序列化,并且minics VM更改哈希码。尽管反序列化后的哈希码不同,但测试仍通过。
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);
}
}
}
关于java - 使用键作为字符串序列化和反序列化 map ,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/2747819/