6

.NET のメソッドについて同様の質問をしました。string.GetHashCode()その時から、異なるマシン間で使用する場合、組み込み型のハッシュ コードの暗黙的な実装に依存できないことを学びました。したがって、Java 実装String.hashCode()も異なるハードウェア構成間で不安定であり、VM 間で異なる動作をする可能性があると想定しています (異なる VM 実装を忘れないでください)。

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

これらすべてのことが頭に浮かびますが、いずれかが十分に強力な理由であると 100% 確信できるわけではありません。この分野におけるあなたの専門知識と経験に感謝します。これは、カスタム ハッシュ アルゴリズムの作成を支持する強力な議論を構築するのに役立ちます。また、実装時にやってはいけないことについてアドバイスをいただければ幸いです。

4

2 に答える 2

13

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

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

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

int 演算を使用します。ここで、s[i] は文字列の i 番目の文字、n は文字列の長さ、^ はべき乗を示します。(空の文字列のハッシュ値はゼロです。)

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

とはいえ、ファイルまたは別のバイト ソースから取得する場合は、取得する方法Stringが難しい場合があります。その場合は、明示的に . を指定すれば問題ありませんCharset。( Strings 自体には異なるエンコーディングがないことに注意してください。エンコーディングは、と の間の変換の仕様です。)byte[]String

于 2013-03-28T22:55:24.477 に答える
3

以下に示すソースコードを見ることができます。私が見る限り (10 秒間の分析の後で)、これはマシンやアーキテクチャ全体で安定しているはずです。そして、ルイは仕様を引用することでこれを確認します。仕様を信じているならなおさらです。:-)

ただし、別の 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;
}
于 2013-03-28T22:57:05.390 に答える