2012-02-24 7 views
5

java mainを実行するたびに異なるhashCode値があるのはなぜですか? 以下のサンプルコードを見てください。あなたが実行するたびに 異なるEnum HashCode生成?

interface testInt{ 

    public int getValue(); 
} 

enum test implements testInt{ 
    A(1), 
    B(2); 

    private int value; 

    private test(int value) { 
     this.value = value; 
    } 

    public int getValue() { 
     return this.value; 
    } 
} 

public static void main(String[] args) { 
    System.out.println(test.A.hashCode()); 
} 

は、コンソール上のさまざまな印刷の値が存在します。 なぜその不一致?

答えて

3

毎回同じ値を使用する場合は、.ordinal()以上を使用してください。getValue()のようにしてください。デフォルトからhashCode()をオーバーライドすることができます。これは、オブジェクトが作成された方法に基づいた数値になります。

+0

はい、私は今getValueを使用しています解決策としてポストを作成して、インターフェイスを実装する際に異なるhashCodeがなぜ表示されるかを確認しました。ありがとう。 –

2

javadocには、それが明確に記載されています。 クラス合理的に実用的である限り

Cオブジェクト内のハッシュコードメソッドのJavadocから、クラス・オブジェクトによって定義されたhashCodeメソッドは、異なるオブジェクトの異なる整数を返すん。 (これは通常、オブジェクトの内部アドレスを整数に変換することで実装されますが、この実装手法はJavaTMプログラミング言語では必要ありません)。

デモコードの実行が異なると、あなたが異なる値を見ることは完全に正常です。

必要に応じて、hashcode()メソッドがjvm呼び出し全体で同じ値を返すようにするには、メソッドをオーバーライドしてカスタム値を返す必要があります。しかし、オブジェクトがハッシュベースのコレクション(ハッシュ衝突の可能性が高まる)で使用される場合、これが致命的になる可能性があることを知っておく必要があります。

+0

私が言ったように。私のここで私をもたらしたのは、Oracle JVM7の単純な列挙型が異なる実行で同じhashCodeを返すという事実でした。しかし、特殊な列挙型にスワップされると、実行ごとにハッシュコードが異なります。 –

3

"異なるJava実装間で、または同じプログラムの異なる実行実行間でも、ハッシュ値が一致する必要はありません。

http://en.wikipedia.org/wiki/Java_hashCode%28%29

http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Object.html#hashCode%28%29

public static void main(String[] args) { 
    System.out.println(test.A.hashCode()); 
    System.out.println(test.A.hashCode()); 
} 

このコードは現在、同じハッシュコードを生成します。

+0

ただし、インターフェイスを実装する列挙型がある場合にのみ発生します。 –

+0

必ずしもそうではありません。プログラムの実行の間に文字列(または他のもの)のハッシュコードを生成するのと比較すると、同じコードを生成するという事実は偶然かもしれません。 – jn1kk

+0

私はここで偶然の一致が正しい単語ではないと思います。それは本当に任意のインターフェイスを実装していないenumsに対して同じhashCode値を返します。それがここに私を指摘したものです。 –

0

JVMの実装によっては、基本的にはEnum.ordinal()が返されます(hashCodeも同様です)が、効果的な変更はありません。 hashCode()値は、実行またはJVM全体で一貫している必要はありません。必要な唯一の契約は、JavaDocsのObject.hashCode()に記述されています。enumで使用されるObjectの実装です。

public class TestEnum { 

    public static void main(String[] args) { 
     System.out.println(Silly.B.hashCode()); 
     System.out.println(Silly.C.hashCode()); 
     System.out.println(Silly.D.hashCode()); 
    } 
} 

enum Silly { 
    B, C, D 
} 

このプログラムはまた、すべての実行時に異なるhashCode()秒を返します。

はまた、インタフェースを実装するhashCode()とは何の関係もないことに注意してください。

+0

Ok、Silly.B.hashCodeは同じhasCodeと違うhasCodeを返します。インターフェースの実装にhashCodeと何も関係がない場合、なぜそれが起こりますか?私はどこに来るのか見ていますか? Silly.B.hashCodeは異なる実行では同じですが、もしSillyが単純なインターフェースを実装するなら、Silly.Aの異なるhashCodeがあります。 –

+0

@VíctorHugo:どのJVMを使用していますか? 1.6.0_26-b03では時々同じ値と異なる値を返すことがありますが、それらは常に同じではありません... –

+0

JVM、jdk1.7.0_02(Oracle) –

0

Enum.hashCodeは、(Object.hashCodeの規則に従う以外の)特定の値を返すように定義されておらず、一般的な実装は特別なことをしません。

なぜですか? HashSetの列挙型(のみ)を使用している場合、またはHashMapのキーとして列挙型を使用している場合は、最適化されたEnumSetまたはEnumMapを代わりに使用する必要があります。 enumがHashSetの他のタイプと一緒に使用されるかどうかを検討してください。インターフェイスを実装するための「標準オプション」がいくつかあるかもしれませんが、他のオプションは独自のオプションを持つことができます。ステートレスなことは何でもします。 1つの複数の列挙型HashSetEnumがハッシュ値の序数を使用していた場合、共通の衝突が発生します。 System.identityHashCodeを使用すると、ロバストな方法でコリジョンが減少します。

public interface Option { 
} 
public enum StandardOptions implements Option { 
    A, B, C 
} 
enum CustomOptions { 
    P, Q, R 
} 
enum MoreOptions { 
    X, Y, Z 
} 

    Set<Option> options = new HashSet<>(); 
    options.add(A); 
    options.add(P); 
    options.add(X); 

私たちは本当にしたくないですA.hashCode() == P.hashCode() == X.hashCode()

関連する問題