我目前需要序列化任意Java对象,因为我想使用Hash作为哈希表的键。在我读取默认hashCode
经常发生冲突的各种警告之后,我想通过MessageDigest
切换到散列来使用替代算法(例如SHA1,...),据说这些算法允许更多条目没有碰撞。 [作为旁注:我知道即使在这里碰撞也可能发生在早期,但我希望增加保持无碰撞的可能性。]
为实现这一目标,我尝试了this StackOverflow post中提出的方法。它使用以下代码获取byte[]
所需的MessageDigest
:
public static byte[] convertToHashableByteArray(Object obj) {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutput out = null;
byte[] byteOutput = null;
try {
out = new ObjectOutputStream(bos);
out.writeObject(obj);
byteOutput = bos.toByteArray();
} catch (IOException io) {
io.printStackTrace();
} finally {
try {
if(out != null) { out.close(); }
} catch(IOException io) {
io.printStackTrace();
}
try {
bos.close();
} catch(IOException io) {
io.printStackTrace();
}
}
return byteOutput;
}
然而,这会导致只有实现serializable
接口的对象被序列化/转换为byte[]
的问题。为了解决此问题,我将toString()
应用于obj
子句中的给定catch
,以强制在所有情况下获得byte[]
:
public static byte[] convertToHashableByteArray(Object obj) {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutput out = null;
byte[] byteOutput = null;
try {
out = new ObjectOutputStream(bos);
out.writeObject(obj);
byteOutput = bos.toByteArray();
} catch (IOException io) {
String stringed = obj.toString();
byteOutput = stringed.getBytes();
} finally {
try {
if(out != null) { out.close(); }
} catch(IOException io) {
io.printStackTrace();
}
try {
bos.close();
} catch(IOException io) {
io.printStackTrace();
}
}
return byteOutput;
}
但是,对我来说,这仍然是完全错误的。所以我的问题是,是否有更好的替代方法将任意对象转换为byte[]
以便能够计算哈希值。优选地,解决方案在不使用额外库的情况下工作,或者使用诸如Apache Commons之类的已建立的库。
(除此之外,我也开放其他方法来获取任意Java对象的SHA1 / SHA512哈希值。)
答案 0 :(得分:0)
也许您可以将对象的UUID用作不可变的唯一标识符?
答案 1 :(得分:0)
这里有很多错误......
如果您仍在阅读并仍不愿意实施第1点,请返回第1点。再一次。
最后回答你的问题,使用hessian序列化。
http://hessian.caucho.com/doc/hessian-overview.xtp
它非常类似于java,只是更快,更短的输出,并允许序列化不实现Serializable接口的对象(冒着搞乱的风险,你需要设置特殊标志来允许)。
答案 2 :(得分:-1)
如果你想序列化给定的对象,我建议你改变你的方法:
public static byte[] convertToHashableByteArray(Serializable obj){
..........
..........
}