簡體   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