문자열에 대한 좋은 해시 함수를 생각하려고합니다. 그리고 문자열의 처음 다섯 문자에 대한 유니 코드 값을 합산하는 것이 좋습니다. 좋은 생각입니까, 아니면 나쁜 생각입니까?
Java 로이 작업을 수행하고 있지만 큰 차이가 있다고는 생각하지 않습니다.
String
스스로 사용할 수 hashCode()
없습니까?
문자열에 대한 좋은 해시 함수를 생각하려고합니다. 그리고 문자열의 처음 다섯 문자에 대한 유니 코드 값을 합산하는 것이 좋습니다. 좋은 생각입니까, 아니면 나쁜 생각입니까?
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
처음 다섯 문자 만 사용하는 것은 좋지 않습니다 . URL과 같은 계층 적 이름을 생각해보십시오. 모두 동일한 해시 코드를 갖습니다 (모두 "http : //"로 시작하기 때문에 해시 맵의 동일한 버킷 아래에 저장되어 성능이 끔찍합니다).
다음은 " Effective Java " 의 String hashCode에 대한 전쟁 이야기입니다 .
1.2 이전의 모든 릴리스에서 구현 된 문자열 해시 함수는 첫 문자부터 시작하여 문자열 전체에 고른 간격으로 최대 16자를 검사했습니다. URL과 같은 대규모 계층 이름 모음의 경우이 해시 함수는 끔찍한 동작을 나타냅니다.
Java로 이것을하고 있다면 왜하고 있습니까? 그냥 .hashCode()
문자열을 불러
.hashCode()
. 오히려 알려진 알고리즘을 사용하십시오.
String::hashCode
은 JDK에 지정되어 있으므로 클래스의 존재만큼 이식성이 뛰어납니다 java.lang.String
.
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();
}
문자열에 대해 좋은 hast 함수를 개발하려고 할 때 홀수로 작업하는 것이 좋습니다. 이 함수는 문자열을 가져 와서 인덱스 값을 반환합니다. 충돌이 적습니다 색인의 범위는 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;
}
당신이 할 수있는 또 다른 일은 "bear"(0 * b) + (1 * e) + (2 * a) + (3 * r) 단어처럼 증가함에 따라 각 문자 int 구문 분석에 색인을 곱하는 것입니다. 재생할 int 값 위의 첫 번째 해시 함수는 "here"와 "hear"에서 충돌하지만 여전히 좋은 고유 값을 제공합니다. 아래의 문자는 각 문자가 증가함에 따라 색인에 곱하기 때문에 "here"및 "hear"와 충돌하지 않습니다.
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에게 다음과 같이 말했습니다. 당신이 그들을 칠 수 있다면 원하는 모든 파란색 제이를 쏴라. 그러나 앵무새를 죽이는 것은 죄라는 것을 기억하라.” 내가 아티 쿠스가 무언가를하는 것은 죄라는 말을들은 유일한 시간이었고, 나는 Maudie 양에게 그것에 대해 물었다. “아버지 말이 맞아요.”그녀가 말했다. “Mockingbirds는 우리가 즐길 수있는 음악을 만드는 것 외에는 아무것도하지 않습니다. 그들은 사람들의 정원을 먹지 않고 옥수수 침대에 둥지를 틀지 않고 한 가지 일을하지 않고 우리를 위해 마음을 노래합니다. 그렇기 때문에 mockingbird를 죽이는 것은 죄입니다.
이것은 출력이 될 것입니다 :
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