web-dev-qa-db-ja.com

Javaオブジェクトのチェックサムを生成する方法

あらゆるタイプのJavaオブジェクトのチェックサムを生成するソリューションを探しています。これは、同じオブジェクトを生成するアプリケーションを実行するたびに同じままです。

Object.hashCode() で試しましたが、APIは

....この整数は、アプリケーションの1つの実行から同じアプリケーションの別の実行まで一貫している必要はありません。

15
Alex

私は同様の問題(XMLファイルの適切なハッシュコードの生成)を抱えていましたが、最善の解決策は MessageDigest またはより高速なものが必要な場合にMD5を使用することであることがわかりました: 高速MD5Object.hashCodeは、高い一意性を保証するには、とにかく短すぎる(32ビットのみ)たびに同じになります。良いハッシュコードを計算するには、64ビットが最小だと思います。 MD5は128ビット長のハッシュコードを生成することに注意してください。これは、この状況で必要とされるよりもさらに多いはずです。

もちろん、MessageDigestを使用するには、最初にオブジェクトをシリアル化(この場合はマーシャル)する必要があります。

9
kopper
public static String getChecksum(Serializable object) throws IOException, NoSuchAlgorithmException {
    ByteArrayOutputStream baos = null;
    ObjectOutputStream oos = null;
    try {
        baos = new ByteArrayOutputStream();
        oos = new ObjectOutputStream(baos);
        oos.writeObject(object);
        MessageDigest md = MessageDigest.getInstance("MD5");
        byte[] thedigest = md.digest(baos.toByteArray());
        return DatatypeConverter.printHexBinary(thedigest);
    } finally {
        oos.close();
        baos.close();
    }
}
13

 private BigInteger checksum(Object obj)throws IOException、NoSuchAlgorithmException {
 
 if(obj == null){
 return BigInteger.ZERO; 
} 
 
 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
 ObjectOutputStream oos = new ObjectOutputStream(baos); 
 oos.writeObject(obj); 
 oos.close(); 
 
 MessageDigest m = MessageDigest.getInstance( "SHA1"); 
 m.update(baos.toByteArray()); 
 
 return new BigInteger(1、m.digest()); 
} 
8
PeterB

シリアル化 を見るべきだと思います。シリアル化メカニズムは同様の問題を解決する必要があるため、どのように実装されているかを確認できます。

しかし、解決しようとしている問題を説明すると、おそらくより正確な解決策が得られます。

5
Roman

ソースを制御する場合は、hashCode()を実装して、実行間で一貫性を保つことができます。

4
Seffi

allJavaオブジェクトに対してこれを実行できるようにしますか?

その場合、hashCode()は機能しません。

一部のクラスでは、hashCode()の定義がより厳密になり、実行全体での同等性が保証されます。たとえば、 String には、明確に定義されたhashCode実装があります。同様に ListSet は、それらに含まれるすべてのオブジェクトがである場合、明確に定義された値を持ちます。 には明確に定義された値があります(一般的な Collection.hashCode()not値を明確に定義する必要があります)。

他のクラスの場合、チェックサムを作成するには、明確に定義された式を使用して再帰的にリフレクションを使用する必要があります。

3
Joachim Sauer

Eclipse IDEを使用している場合は、([ソース]メニューの下に)ハッシュコードと等号関数を生成するアクションがあります。これにより、必要なクラスの属性を選択できます。ハッシュコード。これは、すでに提案されているHashCodeBuilderアプローチの使用に似ています。

または、オブジェクトをバイト配列にストリーミングして、そのMD5を生成することもできます。

2
pauli

Apache commonslangライブラリはHashCodeBuilderクラスを提供し、クラスプロパティから要件を満たすハッシュコードを構築するのに役立ちます。

例:

   public int checksum() {
     // you pick a hard-coded, randomly chosen, non-zero, odd number
     // ideally different for each class
     return new HashCodeBuilder(17, 37).
       append(property1).
       append(property2).
       append(property3).
       toHashCode();
   }

Commons Lang API を参照してください

2
FRotthowe

ハッシュコードはOKです。指定されたクラスはequalsをオーバーライドし、契約の要求に応じてhashcodeもオーバーライドします。契約により、equalstrueを返す場合、ハッシュコードは同じである必要があります。
またはクラスはequalsをオーバーライドしません。この場合、アプリケーションを別の方法で実行しても同じオブジェクトを生成できないため、問題はありません。
唯一の問題は、一部のクラス(Java APIからでも)がequalsのコントラクトを破ることです。

2
Tadeusz Kopec
  1. オブジェクト->文字列(たとえば、GSON-クラスのすべてのフィールドをリストしないようにシリアル化を記述する必要はありません)

  2. String.hashCode()-> int(Object.hashCode()の代わりに!このhashCode()の実現は、メモリ内のアドレスではなく、Stringのコンテンツに依存します---さまざまなアプリの起動、さまざまなスレッドなどで使用できます。)

(または2.文字列-> md5)

0
Evgeny Nozdrev