5

この質問にはすでに答えがあります。

私は尋ねました似たような質問のためにstring.GetHashCode().NETのメソッドです。それから、私たちが異なるマシンにまたがってそれを使うのであれば、私たちは組み込み型のハッシュコードの暗黙の実装に頼ることができないことを学びました。したがって、私はJavaの実装はString.hashCode()ハードウェア構成が異なると不安定になり、VMが異なると動作が異なる可能性があります(異なるVMの実装を忘れないでください)。

現在、ハッシュによってJavaで文字列を安全に数値に変換する方法を検討していますが、ハッシュアルゴリズムはクラスタの異なるノード間で安定している必要があり、使用頻度が高くなるため、評価を早くする必要があります。私のチームメイトはネイティブを主張していますhashCode他のアプローチを再考するためには、いくつかの合理的な議論が必要です。現時点では、マシン構成(x86とx64)、おそらくマシンによってはJVMのベンダーが異なる(私たちの場合はほとんど当てはまりません)、およびアルゴリズムが実行されているマシンに応じたバイトオーダーの違いの違いしか考えられません。走る。もちろん、文字エンコーディングもおそらく考慮されるべきです。

これらすべてのことが私の頭に浮かぶのですが、私はそれらのどちらかが100%確実な理由で十分であると確信しているわけではありません。これは私がカスタムハッシュアルゴリズムを書くことを支持するためにより強い議論を構築するのを助けるでしょう。また、私は何についてのアドバイスをお願い申し上げますしない実装時


  • 文字列ハッシュコードは明確に定義されており、どのJavaプラットフォームでも同じです。 - ZhongYu
  • stackoverflow.com/questions/785091/… - zch
  • @ zhong.j.yuあなたが仮定していますJRockitそしてIBM JVMと同じ実装を持つString#hashCode。 - Luiggi Mendoza
  • のソースコードによると、@ zhong.j.yuStringクラスは、それは十分に安定して見えます。しかし、.NETでそうなることがあるので、それに頼らない理由があります。仮想マシン、ハードウェアの違い、バイト順やエンコードの種類などを考慮すると、Javaのケースは私に非常に似ているようです。 - Ivaylo Slavov
  • @ zhong.j.yuはそうするべきですが、規則にまったく従わないベンダーは常にあります。 - Luiggi Mendoza

2 답변


11

の実装String.hashCode()です指定されたドキュメントの中では、一貫性があることが保証されています。

Stringオブジェクトのハッシュコードは、次のように計算されます。

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

ここで、s [i]は文字列のi番目の文字、nは文字列の長さ、^は指数を表します。 (空の文字列のハッシュ値はゼロです。)

これらの操作はすべて、Java用にプラットフォームに依存せずに実装されています。たとえば、プラットフォームのバイト順は関係ありません。

とはいえ、取得あるStringファイルや別のバイトのソースから取得する場合は、注意が必要です。その場合は、明示的に指定すれば問題ありません。Charset。 (覚えているStringsそれ自体は異なるエンコーディングを持っていません。エンコーディングはコンバージョン〜の間byte[]そしてString。)


  • すべてが仕様(および私がDOとしているコアJavaコンポーネント)によって行われる限り、それは実際には十分に安全なようです。ありがとう - Ivaylo Slavov

3

あなたは見ることができます以下に示すソースコード。私が見ることができるもの(10秒の分析のすべての後)から、これはマシンとアーキテクチャの間で安定しているはずです。そして、Louisはこれをスペックを引用することで確認しています。 :-)

ただし、異なるJREが異なる方法で実装し、仕様に違反することを選択した場合、これは異なる可能性があります。

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;
}


  • ご回答ありがとうございます。私は自分自身でソースコードを調べましたが、問題になる可能性があるものは何も見つかりませんでした。それでも、何かが私にそれが物事がうまくいかないことができる唯一の場所ではないことを教えてくれます。うまくいけば、同じクラスタ内の異なるJVM(異なるベンダ)は私たちの場合ではないでしょう。 - Ivaylo Slavov
  • 仕入先が仕様に違反している場合は、一連の既知の文字列を実行して公式の結果と比較することができます。必ずいくつか実行してください長いですものJavaの初期の頃には、hashCodeメソッドは最初の16文字(おそらく32?)しか考慮していませんでした。ベンダが同じようにしてベンチマークを獲得しようとしているのを見ることができました。 - user949300
  • 良いアドバイス、共有してくれてありがとう。現在のところ、オラクルのJVMに固執するつもりですが、その知識はいつか非常に役立つことが証明されるかもしれません。考えてみると、このような「パフォーマンスの向上」です。多くの望ましくない、予測不可能な動作が発生する可能性があります。他のJVMベンダーがそのカテゴリに入る可能性があるかどうか疑問に思う - Ivaylo Slavov

リンクされた質問


関連する質問

最近の質問