繁体   English   中英

序列化任意Java对象

[英]Serializing arbitrary Java objects

目前,我需要序列化任意Java对象,因为我想使用Hash作为哈希表的键。 在阅读了有关默认hashCode经常创建冲突的各种警告之后,我想通过MessageDigest切换到哈希以使用替代算法(例如SHA1,...),据说该算法允许更多条目而不会发生冲突。 [作为旁注:我知道即使在这里碰撞也可能早早发生,但我想增加保持无碰撞的可能性。]

为此,我尝试了在StackOverflow帖子中提出的方法。 它使用以下代码来获取MessageDigest必需的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) {
        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[] 为了避免这个问题,我在catch子句中将toString()应用于给定的obj ,以在所有情况下强制获取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哈希。)

也许您可以将对象的UUID用作不变的唯一标识符?

这里有很多错...

  1. 您应该具有实现了equals和hashCode的正确键类,而不是使用随机对象。
  2. 序列化性能开销很容易意味着这种映射将比琐碎的迭代搜索要慢。
  3. 在大多数情况下,不应使用默认哈希码,因为对于从业务角度来看“相等”的对象,默认哈希码可能会有所不同。 您应该重新实现哈希码和等号(回到第1点)。 每当它因指针别名而发生冲突时,如果它不能正常工作就无关紧要
  4. 关闭内存流的方法过于复杂。 只是一个接一个地关闭它们,它不是外部资源-如果它失败了,就让它失败,如果发生故障,您不需要100%关闭所有内容。 您还可以使用一种可关闭的实用程序(或尝试/捕获资源)来避免一些开销
  5. 您不需要该字节数组的复杂摘要-使用Arrays.hashCode,它将对您的用例足够好(请记住-无论如何都不要这样做,第1点)

如果您仍在阅读并且仍然不愿意执行第1点,请回到第1点。然后再次。 然后再次。

最后使用粗麻布序列化来回答您的问题。

http://hessian.caucho.com/doc/hessian-overview.xtp

它与Java语言非常相似,只是输出更快,更短,并且可以对未实现Serializable接口的对象进行序列化(冒着麻烦的危险,您需要设置特殊标志以允许这样做)。

如果您想序列化一个给定的对象,我建议您像这样更改您的方法:

public static byte[] convertToHashableByteArray(Serializable obj){
     ..........
     ..........
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM