62

hashCode()メソッドはJavaでどのような値を返しますか?

オブジェクトのメモリ参照であると読みました...のハッシュ値new Integer(1)は1です。のハッシュ値String("a")は97です。

私は混乱しています:それはASCIIですか、それともどのような種類の値ですか?

4

10 に答える 10

53

によって返される値はhashCode()、オブジェクトのメモリアドレスであることが保証されているわけではありません。クラスでの実装はわかりませんが、ObjectほとんどのクラスはhashCode()、意味的に同等である(ただし、同じインスタンスではない)2つのインスタンスが同じ値にハッシュされるようにオーバーライドすることに注意してください。hashCodeこれは、クラスがSetなど、との整合性に依存する別のデータ構造内で使用される可能性がある場合に特に重要ですequals

hashCode()があっても、オブジェクトのインスタンスを一意に識別するものはありません。基になるポインタに基づくハッシュコードが必要な場合(Sunの実装など)、-を使用します。これにより、オーバーライドされているかどうかに関係なくSystem.identityHashCode()、デフォルトのメソッドに委任されます。hashCode

それでも、System.identityHashCode()複数のオブジェクトに対して同じハッシュを返すこともできます。説明についてはコメントを参照してください。ただし、同じが2つ見つかるまでオブジェクトを継続的に生成するプログラムの例を次に示しますSystem.identityHashCode()System.identityHashCode()これを実行すると、平均して約86,000のLongラッパーオブジェクト(およびキーの整数ラッパー)をマップに追加した後、一致する2つのがすぐに見つかります。

public static void main(String[] args) {
    Map<Integer,Long> map = new HashMap<>();
    Random generator = new Random();
    Collection<Integer> counts = new LinkedList<>();

    Long object = generator.nextLong();
    // We use the identityHashCode as the key into the map
    // This makes it easier to check if any other objects
    // have the same key.
    int hash = System.identityHashCode(object);
    while (!map.containsKey(hash)) {
        map.put(hash, object);
        object = generator.nextLong();
        hash = System.identityHashCode(object);
    }
    System.out.println("Identical maps for size:  " + map.size());
    System.out.println("First object value: " + object);
    System.out.println("Second object value: " + map.get(hash));
    System.out.println("First object identityHash:  " + System.identityHashCode(object));
    System.out.println("Second object identityHash: " + System.identityHashCode(map.get(hash)));
}

出力例:

Identical maps for size:  105822
First object value: 7446391633043190962
Second object value: -8143651927768852586
First object identityHash:  2134400190
Second object identityHash: 2134400190
于 2010-03-11T18:35:51.553 に答える
51

ハッシュコードは、呼び出されたオブジェクトの状態を表す整数値です。そのため、 1に設定すると、ハッシュコードとその値は同じであるIntegerため、「1」のハッシュコードが返されます。Integer's文字のハッシュコードは、ASCII文字コードと同じです。hashCodeカスタムタイプを作成する場合は、現在のインスタンスの状態を最もよく表す適切な実装を作成する責任があります。

于 2010-03-11T18:33:37.453 に答える
24

それらがどのように実装されているかを知りたい場合は、ソースを読むことをお勧めします。+ IDEを使用している場合は、関心のあるメソッドを+実行して、メソッドがどのように実装されているかを確認できます。それができない場合は、ソースをグーグルで検索できます。

たとえば、Integer.hashCode()は次のように実装されます。

   public int hashCode() {
       return value;
   }

およびString.hashCode()

   public int hashCode() {
       int h = hash;
       if (h == 0) {
           int off = offset;
           char val[] = value;
           int len = count;

           for (int i = 0; i < len; i++) {
               h = 31*h + val[off++];
           }
           hash = h;
       }
       return h;
   }
于 2010-03-13T06:49:20.787 に答える
8

このhashCode()メソッドは、オブジェクトを識別するためによく使用されます。Object実装はオブジェクトのポインタ(実際のポインタではなく、一意のIDなど)を返すと思います。ただし、ほとんどのクラスはメソッドをオーバーライドします。Stringクラスのように。2つのStringオブジェクトには同じポインターはありませんが、同じです。

new String("a").hashCode() == new String("a").hashCode()

の最も一般的な用途hashCode()HashtableHashSetなどです。

Java APIオブジェクトhashCode()

編集:(最近の反対票のため、JVMパラメーターについて読んだ記事に基づいています)

JVMパラメータ-XX:hashCodeを使用すると、hashCodeの計算方法を変更できます(Java Specialists'NewsletterのIssue222を参照)

HashCode == 0:オブジェクトが見つかったメモリ内の場所とは関係なく、単に乱数を返します。私の知る限り、シードのグローバルな読み取り/書き込みは、多数のプロセッサを搭載したシステムには最適ではありません。

HashCode == 1:ハッシュコード値をカウントアップします。どの値で開始するかはわかりませんが、かなり高いようです。

HashCode == 2:常にまったく同じIDハッシュコード1を返します。これは、オブジェクトIDに依存するコードをテストするために使用できます。上記の例でJavaChampionTestがKirkのURLを返した理由は、すべてのオブジェクトが同じハッシュコードを返していたためです。

HashCode == 3:ゼロから始めてハッシュコード値をカウントアップします。スレッドセーフではないように見えるため、複数のスレッドが同じハッシュコードでオブジェクトを生成する可能性があります。

HashCode == 4:これは、オブジェクトが作成されたメモリの場所と何らかの関係があるようです。

HashCode> = 5:これはJava 8のデフォルトのアルゴリズムであり、スレッドごとのシードがあります。Marsagliaのxor-shiftスキームを使用して、疑似乱数を生成します。

于 2010-03-11T18:48:08.240 に答える
6

オブジェクトのメモリ参照だと読みました。

Object.hashCode()約14年前にメモリアドレスを返すために使用された番号。それ以来ではありません。

値のタイプは何ですか

それが何であるかは、あなたが話しているクラスと、それが `Object.hashCode()をオーバーライドしたかどうかに完全に依存します。

于 2010-03-13T01:26:51.787 に答える
3

OpenJDKソース(JDK8)から:

デフォルトの5を使用して、ハッシュコードを生成します。

product(intx, hashCode, 5,                                                
      "(Unstable) select hashCode generation algorithm")       

いくつかの定数データと、スレッドごとに開始されたシードを使用してランダムに生成された数値:

// thread-specific hashCode stream generator state - Marsaglia shift-xor form
  _hashStateX = os::random() ;
  _hashStateY = 842502087 ;
  _hashStateZ = 0x8767 ;    // (int)(3579807591LL & 0xffff) ;
  _hashStateW = 273326509 ;

次に、この関数はhashCode(上記で指定されたデフォルトは5)を作成します。

static inline intptr_t get_next_hash(Thread * Self, oop obj) {
  intptr_t value = 0 ;
  if (hashCode == 0) {
     // This form uses an unguarded global Park-Miller RNG,
     // so it's possible for two threads to race and generate the same RNG.
     // On MP system we'll have lots of RW access to a global, so the
     // mechanism induces lots of coherency traffic.
     value = os::random() ;
  } else
  if (hashCode == 1) {
     // This variation has the property of being stable (idempotent)
     // between STW operations.  This can be useful in some of the 1-0
     // synchronization schemes.
     intptr_t addrBits = cast_from_oop<intptr_t>(obj) >> 3 ;
     value = addrBits ^ (addrBits >> 5) ^ GVars.stwRandom ;
  } else
  if (hashCode == 2) {
     value = 1 ;            // for sensitivity testing
  } else
  if (hashCode == 3) {
     value = ++GVars.hcSequence ;
  } else
  if (hashCode == 4) {
     value = cast_from_oop<intptr_t>(obj) ;
  } else {
     // Marsaglia's xor-shift scheme with thread-specific state
     // This is probably the best overall implementation -- we'll
     // likely make this the default in future releases.
     unsigned t = Self->_hashStateX ;
     t ^= (t << 11) ;
     Self->_hashStateX = Self->_hashStateY ;
     Self->_hashStateY = Self->_hashStateZ ;
     Self->_hashStateZ = Self->_hashStateW ;
     unsigned v = Self->_hashStateW ;
     v = (v ^ (v >> 19)) ^ (t ^ (t >> 8)) ;
     Self->_hashStateW = v ;
     value = v ;
  }

  value &= markOopDesc::hash_mask;
  if (value == 0) value = 0xBAD ;
  assert (value != markOopDesc::no_hash, "invariant") ;
  TEVENT (hashCode: GENERATE) ;
  return value;
}

したがって、少なくともJDK8では、デフォルトがランダムスレッド固有に設定されていることがわかります。

于 2018-09-26T12:04:40.927 に答える
3

定義:String hashCode()メソッドは、Stringのハッシュコード値を整数として返します。

構文: public int hashCode()

ハッシュコードは、以下の式を使用して計算されます

s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]

where:

s is ith character in the string
n is length of the string
^ is exponential operand

例: たとえば、文字列「abc」のハッシュコードを計算する場合は、以下の詳細があります

s[] = {'a', 'b', 'c'}
n = 3

したがって、ハッシュコード値は次のように計算されます。

s[0]*31^(2) + s[1]*31^1 + s[2]
= a*31^2 + b*31^1 + c*31^0
= (ASCII value of a = 97, b = 98 and c = 99)
= 97*961 + 98*31 + 99 
= 93217 + 3038 + 99
= 96354

したがって、「abc」のハッシュコード値は96354です。

于 2021-02-09T20:41:44.190 に答える
2

Object.hashCode()は、メモリが正しく機能する場合(JavaDocでjava.lang.Objectを確認)、実装に依存し、オブジェクトに応じて変化します(Sun JVMは、オブジェクトへの参照の値から値を取得します) )。

重要なオブジェクトを実装していて、それらをHashMapまたはHashSetに正しく格納したい場合は、hashCode()とequals()をオーバーライドする必要があることに注意してください。hashCode()は好きなことを行うことができます(完全に合法ですが、1を返すのは最適ではありません)が、equals()メソッドがtrueを返す場合、両方のオブジェクトのhashCode()によって返される値が等しいことが重要です。

hashCode()とequals()の混乱と理解の欠如は、バグの大きな原因です。Object.hashCode()およびObject.equals()のJavaDocsに完全に精通していることを確認してください。また、費やした時間がそれ自体で支払われることを保証します。

于 2010-03-11T18:54:12.563 に答える
0

Javadocから:

合理的に実用的である限り、クラスObjectによって定義されたhashCodeメソッドは、個別のオブジェクトに対して個別の整数を返します。(これは通常、オブジェクトの内部アドレスを整数に変換することによって実装されますが、この実装手法はJava™プログラミング言語では必要ありません。)

https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html#hashCode--

于 2018-01-05T17:46:28.467 に答える
0

誰もこれについて言及していないことに驚いていますが、Objectクラス以外の人にとって最初のアクションは、多くのクラスのソースコードを読み取ることですが.hashcode()Objectその場合、JVMに応じていくつかの異なる興味深いことが起こる可能性があります。実装。Object.hashcode()への呼び出しSystem.identityHashcode(object)

実際、メモリ内でオブジェクトアドレスを使用することは古代の歴史ですが、多くの人は、この動作を制御できること、およびNが[0-5]の数値であるObject.hashcode()jvm引数を介してどのように計算されるかを認識していません。-XX:hashCode=N

0 – Park-Miller RNG (default, blocking)
1 – f(address, global_statement)
2 – constant 1
3 – serial counter
4 – object address
5 – Thread-local Xorshift

アプリケーションによっては、が呼び出されたときに予期しないパフォーマンスヒット.hashcode()が発生する場合があります。その場合、グローバル状態やブロックを共有するアルゴリズムの1つを使用している可能性があります。

于 2022-01-11T11:43:31.170 に答える