文字列よりも数値を比較しやすいため、文字列などにはハッシュ(文字列やオブジェクトを数値に変換する)が使われているそうです。本当の場合、これの理由は何ですか?
これは必ずしも当てはまるわけではありませんが、おそらくほとんどの場合当てはまります。
次の状況を考慮してください。
文字列「apples」と「oranges」を比較したいと思います。 "apples" == "oranges"だけを判別したい場合は、各文字列の最初の文字を比較するだけで済みます: 'a'!= 'o' => "apples"!= "oranges"。文字列をハッシュしてから比較を行うと、結果の整数を比較する前に両方の文字列を解析してハッシュアルゴリズムに入力する必要があるため、処理速度が大幅に低下します。
ただし、この比較を何度も行う必要があり、「オレンジ」と「オランウータン」を何度も比較している場合は、すべての文字列を1回ハッシュして整数の比較を何度も行うと、うまくいきます。もっと早く。これは、ハッシュマップが基づいている原則です。
ただし、文字列のハッシュは直接等しい比較に役立ちます。文字列が字句的に互いに大きいか小さいかを判断できないため、ハッシュ方式を使用して文字列を並べ替えることはできません。 (これが、JavaのHashMapが順序付けられていない理由です)。
2つの数値を比較することは、2つの文字列(同じ数値を表す)を比較するよりもはるかに高速です。 2つの数値を比較するには、個々のビットを比較するだけでよく、AND、XOR、2の補数などのいずれかを使用して超高速で実行できます。
2つの文字列の比較は非常に遅く、費用がかかります。ほとんどのアルゴリズムでは、文字列全体を反復処理し、各文字を照合する必要があります。
たとえば、9と12(false)を比較したいとします。数値比較のために、アルゴリズムが個々のビットを比較すると仮定しましょう。 9 = 1001 12 = 1100
ここで、最悪の場合のアルゴリズムは4ビットを比較します。
ここで、「9」と「12」を文字列として表すと、それぞれ16ビットとしてメモリに格納されます(リコール:JavaはUTF-16を使用してメモリ内の文字列を表す)。文字列比較アルゴリズムに渡されます。実際、Javaの実際の文字列比較関数は次のとおりです。
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = count;
if (n == anotherString.count) {
char v1[] = value;
char v2[] = anotherString.value;
int i = offset;
int j = anotherString.offset;
while (n-- != 0) {
if (v1[i++] != v2[j++])
return false;
}
return true;
}
}
return false;
}
ご覧のとおり、文字列の比較にはさらに多くのことがあります。
一般に、ほとんどのコンピューターには、整数、longなどを比較するための単一の命令があり、最大で2、3の命令サイクルが必要です。文字列は通常、ユーティリティ関数/メソッドによって比較されます(このルールには奇妙な例外がある場合があります)。
in Javaたとえば、文字列は基本的に次のように表されます。
/** The value is used for character storage. */
private final char value[];
/** The offset is the first index of the storage that is used. */
private final int offset;
/** The count is the number of characters in the String. */
private final int count;
そしてequalsメソッドは
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = count;
if (n == anotherString.count) {
char v1[] = value;
char v2[] = anotherString.value;
int i = offset;
int j = anotherString.offset;
while (n-- != 0) {
if (v1[i++] != v2[j++])
return false;
}
return true;
}
}
return false;
Equalsメソッドは、this == anObjectとn == anotherString.countの両方を実行します。どちらも、文字の比較を開始する前であっても、基本的に整数で比較します。整数比較にかかる単一の命令よりもはるかに時間がかかります
C文字列比較はより単純/高速 Java同等のものよりも優れていますが、パススルーごとに何らかのループと複数の命令が含まれますループ。
これは、整数比較に必要な1つの命令よりも時間がかかります
Javaの文字列を比較するのはメソッドですが、Javaのハッシュは、別の理由で、Object.hashCode()は、コレクション内のクイック検索のためにハッシュテーブルで使用されます。
はい、しかしそれはハッシュとは何の関係もありません。
数値の比較には、ビットを比較する単純なハードウェア命令が含まれます。
文字列の比較には、(a)異なる文字が見つかるまで両方の文字列を繰り返す(固定サイズの数字とは異なります)および(b)多くのUnicodeマジック(異なる長さの異なる文字列は実際には等しくなる可能性があり、異なるコード内の異なる文字ブロックの比較は異なります)。
ハッシュは通常、文字列を配列インデックスに変換するために使用されます。