文字列に適したハッシュ関数を考えています。そして、文字列の最初の5文字のUnicode値を合計するのは良い考えかもしれないと考えていました(5文字であると想定し、それ以外の場合は終了する場所で停止します)。それは良い考えでしょうか、それとも悪い考えですか?
私はこれをJavaで行っていますが、それが大きな違いをもたらすとは思いません。
String
自分のものを使用できないのですhashCode()
か?
文字列に適したハッシュ関数を考えています。そして、文字列の最初の5文字のUnicode値を合計するのは良い考えかもしれないと考えていました(5文字であると想定し、それ以外の場合は終了する場所で停止します)。それは良い考えでしょうか、それとも悪い考えですか?
私はこれをJavaで行っていますが、それが大きな違いをもたらすとは思いません。
String
自分のものを使用できないのですhashCode()
か?
回答:
通常、ハッシュはそうでない場合、合計しないだろうstop
とpots
同じハッシュを持つことになります。
また、最初のn文字に制限しないと、家と家のハッシュが同じになるためです。
通常、ハッシュは値を取り、素数を掛けます(一意のハッシュを生成する可能性が高くなります)。したがって、次のようなことを行うことができます。
int hash = 7;
for (int i = 0; i < strlen; i++) {
hash = hash*31 + charAt(i);
}
セキュリティが必要な場合は、Java暗号を使用できます。
import java.security.MessageDigest;
MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
messageDigest.update(stringToEncrypt.getBytes());
String encryptedString = new String(messageDigest.digest());
おそらくString.hashCode()を使用する必要があります。
あなたが実際にhashCodeを実装したい場合:
パフォーマンスを向上させるために、オブジェクトの重要な部分をハッシュコードの計算から除外したくありません-Joshua Bloch、Effective Java
最初の5つの文字を使用することである悪い考え。URLなどの階層名について考えてみてください。それらはすべて同じハッシュコードを持ちます(すべて「http://」で始まるため、ハッシュマップの同じバケットの下に格納され、ひどいパフォーマンスを示します。
これは、「Effective Java」のString hashCodeを言い換えた戦争の話です。
1.2より前のすべてのリリースで実装された文字列ハッシュ関数は、最初の文字から始めて、文字列全体に等間隔に配置された最大16文字を調べました。URLなどの階層名の大規模なコレクションの場合、このハッシュ関数はひどい動作を示しました。
あなたがJavaでこれをしているなら、なぜそれをしているのですか?.hashCode()
文字列を呼び出すだけ
.hashCode()
。むしろ、いくつかの既知のアルゴリズムを使用してください。
String::hashCode
はJDKで指定されているため、クラスの存在そのものと同じくらい移植可能java.lang.String
です。
GuavaHashFunction
(javadoc)は、適切な非暗号強度のハッシュを提供します。
404
d。
Nickが提供するこの関数は優れていますが、new String(byte [] bytes)を使用してStringに変換すると失敗します。この機能を使用してそれを行うことができます。
private static final char[] hex = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
public static String byteArray2Hex(byte[] bytes) {
StringBuffer sb = new StringBuffer(bytes.length * 2);
for(final byte b : bytes) {
sb.append(hex[(b & 0xF0) >> 4]);
sb.append(hex[b & 0x0F]);
}
return sb.toString();
}
public static String getStringFromSHA256(String stringToEncrypt) throws NoSuchAlgorithmException {
MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
messageDigest.update(stringToEncrypt.getBytes());
return byteArray2Hex(messageDigest.digest());
}
これは誰かを助けることができるかもしれません
// djb2 hash function
unsigned long hash(unsigned char *str)
{
unsigned long hash = 5381;
int c;
while (c = *str++)
hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
return hash;
}
FNV-1は文字列に適したハッシュ関数であると噂されています。
長い文字列(たとえば、約200文字より長い)の場合、MD4ハッシュ関数から優れたパフォーマンスを得ることができます。暗号化機能として、約15年前に破られましたが、非暗号化の目的では、それはまだ非常に優れており、驚くほど高速です。Javaのコンテキストでは、16ビットのchar
値を32ビットのワードに変換する必要があります。たとえば、そのような値をペアにグループ化するなどです。JavaでのMD4の高速実装は、sphlibにあります。おそらく、教室の割り当てのコンテキストではやりすぎですが、それ以外は試す価値があります。
業界標準の実装を見たい場合は、java.security.MessageDigestを参照してください。
「メッセージダイジェストは、任意サイズのデータを受け取り、固定長のハッシュ値を出力する安全な一方向ハッシュ関数です。」
public String hashString(String s) throws NoSuchAlgorithmException {
byte[] hash = null;
try {
MessageDigest md = MessageDigest.getInstance("SHA-256");
hash = md.digest(s.getBytes());
} catch (NoSuchAlgorithmException e) { e.printStackTrace(); }
StringBuilder sb = new StringBuilder();
for (int i = 0; i < hash.length; ++i) {
String hex = Integer.toHexString(hash[i]);
if (hex.length() == 1) {
sb.append(0);
sb.append(hex.charAt(hex.length() - 1));
} else {
sb.append(hex.substring(hex.length() - 2));
}
}
return sb.toString();
}
文字列の良い速関数を開発しようとするときに奇数で作業するのは良い考えです。この関数は文字列を取り、インデックス値を返します。これまでのところ、その動作はかなり良好です。衝突が少ない。インデックスの範囲は0〜300ですが、それ以上かもしれませんが、「電気機械工学」のような長い単語を使っても、これまでこれ以上高くはありません。
int keyHash(string key)
{
unsigned int k = (int)key.length();
unsigned int u = 0,n = 0;
for (Uint i=0; i<k; i++)
{
n = (int)key[i];
u += 7*n%31;
}
return u%139;
}
あなたができる別のことは、単語「クマ」(0 * b)+(1 * e)+(2 * a)+(3 * r)のように増加するにつれて、各文字のintパースをインデックスで乗算することです遊ぶint値。上記の最初のハッシュ関数は、「ここ」と「聞く」で衝突しますが、いくつかの優れた一意の値を提供するのに優れています。以下のコードは、「ここ」や「聞く」と衝突しません。増加するにつれて、各文字にインデックスを掛けているからです。
int keyHash(string key)
{
unsigned int k = (int)key.length();
unsigned int u = 0,n = 0;
for (Uint i=0; i<k; i++)
{
n = (int)key[i];
u += i*n%31;
}
return u%139;
}
これが、私が作成したハッシュテーブルに使用する簡単なハッシュ関数です。基本的にはテキストファイルを取得し、アルファベット順を表すインデックスにすべての単語を格納します。
int generatehashkey(const char *name)
{
int x = tolower(name[0])- 97;
if (x < 0 || x > 25)
x = 26;
return x;
}
これが基本的に行うことは、単語が最初の文字に従ってハッシュされることです。したがって、「a」で始まる単語のハッシュキーは0になり、「b」は1になり、「z」は25になります。数値と記号のハッシュキーは26になります。 ; 特定の単語がハッシュテーブルのどこにインデックス付けされるかを簡単かつ迅速に計算できます。これは、次のようにすべてがアルファベット順であるためです。コードは、次の場所にあります:https : //github.com/abhijitcpatil/general
次のテキストを入力として与える: Atticusはある日Jemに次のように言いました。「裏庭のブリキ缶で撃ったほうがいいですが、鳥を追いかけるつもりです。あなたがそれらを打つことができるなら、あなたが望むすべてのブルージェイズを撃ってください、しかしそれがモッキンバードを殺すのは罪であることを忘れないでください。」アッティカスが何かをするのは罪だと言うのを聞いたのはそのときだけだったので、ミス・オーディに聞いた。「あなたの父親の権利」と彼女は言った。「モッキンバードは私たちが楽しむために音楽を作る以外に何もしません。彼らは人々の庭を食べ尽くしたり、トウモロコシのベビーベッドに巣を作ったりすることはありません。彼らは一つのことをするのではなく、私たちのために彼らの心を歌います。だからこそ、モッキンバードを殺すのは罪なのです。
これは出力になります:
0 --> a a about asked and a Atticus a a all after at Atticus
1 --> but but blue birds. but backyard
2 --> cribs corn can cans
3 --> do don’t don’t don’t do don’t do day
4 --> eat enjoy. except ever
5 --> for for father’s
6 --> gardens go
7 --> hearts heard hit
8 --> it’s in it. I it I it’s if I in
9 --> jays Jem
10 --> kill kill know
11 -->
12 --> mockingbird. music make Maudie Miss mockingbird.”
13 --> nest
14 --> out one one only one
15 --> people’s
16 --> 17 --> right remember rather
18 --> sin sing said. she something sin say sin Shoot shot said
19 --> to That’s their thing they They to thing to time the That to the the tin to
20 --> us. up us
21 -->
22 --> why was was want
23 -->
24 --> you you you’ll you
25 -->
26 --> “Mockingbirds ” “Your ‘em “I’d
これにより、衝突が回避され、計算でシフトを使用するまで高速になります。
int k = key.length();
int sum = 0;
for(int i = 0 ; i < k-1 ; i++){
sum += key.charAt(i)<<(5*i);
}