Java String의 hashCode 값은 (String.hashCode ()) :
s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
다음 표현식이 거짓으로 평가되는 상황 (예 : JVM 버전, 공급 업체 등)이 있습니까?
boolean expression = "This is a Java string".hashCode() == 586653468
업데이트 #1 :대답이 "예, 그런 상황이 있습니다"라고 주장하는 경우 "This is a Java string".hashCode ()! = 586653468의 구체적인 예를 들어주십시오. 가능한 구체적 / 구체적으로 작성하십시오.
업데이트 #2 :우리는 hashCode ()의 구현 세부 사항에 의존하는 것이 일반적으로 나쁘다는 것을 압니다. 그러나, 나는 String.hashCode ()에 대해 구체적으로 말하고있다. 그래서 String.hashCode ()에 초점을 맞춘다. Object.hashCode ()는이 질문에서 전혀 관련이 없습니다.
Java 1.2만큼 먼 저 설명서를 볼 수 있습니다.
그것은 사실이지만일반적으로당신은 해시 코드 구현을 그대로 유지해서는 안되며, 현재 문서화 된 동작이다.java.lang.String
따라서 기존 계약을 위반하는 것으로 변경 될 수 있습니다.
가능하다면 버전 등에서 동일하게 머무르는 해시 코드에 의존해서는 안됩니다.하지만 내 마음에는java.lang.String
알고리즘이 단순하기 때문에 특별한 경우입니다.있다지정된 알고리즘 ... 알고리즘이 지정되기 전에 릴리스와의 호환성을 포기할 의향이있는 한.
JDK 1.0 및 1.1 및> = 1.2에 대해 뭔가를 발견했습니다.
JDK 1.0.x 및 1.1.x에서는, hashCode 긴 Strings가 작동하는 함수 매 n 번째 문자를 샘플링합니다. 이 꽤 잘 당신이 가질 것이라고 보장 같은 문자열에 해싱하는 많은 문자열 가치, 따라서 Hashtable 속도가 느려집니다. 조회. JDK 1.2에서이 함수는 결과가 배가되었다. 지금까지 31 개를 추가하여 다음 문자. 이것은 조금 느리지 만 훨씬 낫다. 충돌을 피하십시오. 출처:http://mindprod.com/jgloss/hashcode.html
숫자가 필요하기 때문에 다른 점이 있습니다 : 해시 코드 대신 CRC32 또는 MD5를 사용하는 것이 어떻습니까? 토론이나 걱정할 필요가 없습니다.
특정 값과 동일한 해시 코드에 의존해서는 안됩니다. 같은 실행 내에서 일관된 결과를 반환합니다. API 문서는 다음과 같이 말합니다.
hashCode의 일반 규약은 다음과 같습니다.
- Java 어플리케이션의 실행 중에 같은 오브젝트로 2 회 이상 불려 갈 때마다 hashCode 메소드는, 오브젝트의 equals 비교로 사용 된 정보가 변경되지 않으면, 같은 정수를 일관되게 돌려 줄 필요가 있습니다. 이 정수는 응용 프로그램의 한 실행에서 동일한 응용 프로그램의 다른 실행으로 일관성을 유지할 필요가 없습니다.
편집하다String.hashCode ()의 javadoc에서는, String의 해시 코드의 계산 방법을 지정하고 있기 (위해) 때문에,이 위반은 public API 사양을 위반하게됩니다.
위에서 말했듯이, 일반적으로 클래스의 해시 코드에 의존해서는 안됩니다. 이후의 실행에서도동일한 신청~에같은 VM다른 해시 값을 생성 할 수 있습니다. AFAIK Sun JVM의 해시 함수는 모든 실행에서 동일한 해시를 계산하지만 보장되지는 않습니다.
이것은 이론적이지 않다는 것을 유의하십시오. java.lang.String의 해시 함수변경되었습니다.JDK1.2에서 (오래된 해시는 URL이나 파일 이름과 같은 계층 적 문자열에 문제가있었습니다. 끝에 만 다른 문자열에 대해 동일한 해시를 생성하는 경향이있었습니다).
java.lang.String은 특별한 경우입니다. hashCode ()의 알고리즘이 (지금) 문서화되었으므로 아마도 이에 의존 할 수 있습니다. 나는 여전히 나쁜 습관이라고 생각할 것이다. 특수하고 문서화 된 속성을 가진 해쉬 알고리즘이 필요하다면 하나만 쓰면됩니다 :-).
걱정할 또 다른 (!) 문제는 Java의 초기 / 후기 버전 간의 구현 변경 가능성입니다. 구현 세부 사항이 돌로 설정되어 있다고 생각하지 않으므로 잠재적으로미래Java 버전으로 인해 문제가 발생할 수 있습니다.
최종선은, 나는 의지를 의지하지 않을 것이다hashCode()
.
아마도이 메커니즘을 사용하여 실제로 어떤 문제를 해결하려고하는지 강조 할 수 있으며 이는보다 적절한 접근 방법을 강조합니다.
switch
특정 고정 해시 코드에 의존하는 코드를 컴파일하는 문자열에 대한 명령문.String
해시 코드 알고리즘이 기존 코드를 확실히 깨뜨릴 것입니다 ... - Holger
질문에 답하고 토론을 계속하지 말라. 아파치 하모니 JDK 구현은 다른 알고리즘을 사용하는 것처럼 보입니다. 적어도 완전히 다른 것처럼 보입니다.
Sun JDK
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;
}
아파치 하모니
public int hashCode() {
if (hashCode == 0) {
int hash = 0, multiplier = 1;
for (int i = offset + count - 1; i >= offset; i--) {
hash += value[i] * multiplier;
int shifted = multiplier << 5;
multiplier = shifted - multiplier;
}
hashCode = hash;
}
return hashCode;
}
직접 확인해보십시오 ...
s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
내가 잘못 본 것이 아니라면, 안드로이드는 변경없이 Sun 객체의 String 객체 구현을 사용하기 때문입니다. - K_7
변경 사항과 호환되지 않는 VM이 걱정된다면 기존의 해시 코드 구현을 자신의 유틸리티 클래스에 복사하고이를 사용하여 해시 코드를 생성하십시오.