그것은 가능한 하나의 동일한 객체, 특히string
또는 원시 또는 매우 간단한 유형 (예 :struct
)를 사용하여.GetHashCode()
다른 컴퓨터에서 호출 할 때 어떻게해야합니까?
예를 들어, 표현식"Hello World".GetHashCode()
다른 컴퓨터에서 다른 값을 생성합니다. 나는 주로 C #.NET을 요구하고 있지만 이것은 자바 또는 다른 언어에도 적용될 수 있다고 생각하십니까?
편집하다:
아래의 답변과 의견에서 지적한 바와 같이,.GetHashCode()
될 수있다.재정의하다, 프레임 워크의 다른 버전간에 생성 된 결과에 대한 보장이 없습니다. 그러므로 내가 단순한 타입을 염두에두고 있음을 분명히하는 것이 중요하다. (그러므로 상속 될 수 없다.GetHashCode()
재정의 됨) 모든 컴퓨터에서 동일한 버전의 프레임 워크를 사용하고 있습니다.
짧은 대답 : 네.
그러나 짧은 대답은 재미 있지 않습니까?
구현할 때GetHashCode()
다음과 같은 보증을해야합니다.
언제
GetHashCode()
동일한 객체로 간주되어야하는 다른 객체에서 호출되면이 응용 프로그램 도메인에서 동일한 값이 반환됩니다.
그게 전부 야. 가능한 한 많은 양의 다른 객체로 비트를 퍼뜨려야하지만, 그렇게 오래 걸리지는 마십시오. 처음에는 해시의 모든 이점보다 중요합니다.) 그리고 코드 네가 그렇게하지 않으면 빨아 먹을거야.하지만 실제로는 깨지지 않을거야. 당신이 그렇게 멀리 가지 않으면 깨질 것입니다. 그 이유는 다음과 같습니다.
dict[myObj] = 3;
int x = dict[myObj];//KeyNotFoundException
괜찮아. 내가 구현한다면GetHashCode()
, 왜 내가 그 이상으로 나아갈 수 있으며, 왜 그렇게하지 않을 수 있습니까?
첫째, 왜 내가하지 않았을까요?
어쩌면 그것은 어셈블리의 약간 다른 버전 일 것이고 빌드 사이에서 개선되었거나 적어도 시도되었습니다.
어쩌면 하나는 32 비트이고 하나는 64 비트이고 나는 효율을 높이기 위해 열매를 맺고 서로 다른 워드 크기를 사용하기 위해 서로 다른 알고리즘을 선택했습니다 (이것은 전례가 아닙니다, 특히 콜렉션이나 문자열과 같은 객체를 해싱 할 때) .
아마도 "평등 한"객체를 구성하는 요소를 결정할 때 고려해야 할 요소는 이런 종류의 방식으로 시스템마다 다를 수 있습니다.
어쩌면 나는 실수로 동료가 실수로 내 해시 코드에 의존하는 모든 경우를 잡기 위해 의도적으로 다른 빌드를 가진 다른 시드를 소개합니다! (필자는 MS가string.GetHashCode()
, 믿을만하고 믿을만한 곳에서들을 수 있는지 기억이 안납니다.)
주로 그래도 첫 번째 두 가지 이유 중 하나입니다.
왜 그런 보장을 해줄까요?
아마 그렇게한다면, 우연히 만날 것입니다. 요소가 하나의 정수 id만을 기준으로 동등 함을 비교할 수 있다면 해시 코드로 사용할 것입니다. 덜 좋은 해시를 위해 다른 것은 더 많은 작업이 될 것입니다. 나는 이것을 바꿀 가능성이 없기 때문에 나는 그렇게 할 것이다.
내가 할 수있는 또 다른 이유는, 나는 그 보증을 나 자신으로 원한다는 것이다. 내가 그것을 제공 할 수 없다고 말할 것도없고, 단지 그럴 필요가 없다.
좋아, 실용적인 것을 찾아 보자. 기계 독립적 보증이 필요한 경우가 있습니다. 반대편을 원할지도 모르는 경우가 있습니다.
먼저 논리를 확인하십시오. 충돌을 처리 할 수 있습니까? 좋아, 그러면 시작하겠습니다.
그것이 자신의 수업 인 경우 그러한 보증을 제공하고 문서화하면 완료됩니다.
클래스가 아닌 경우 구현IEqualityComparer<T>
그것을 제공하는 방식으로. 예 :
public class ConsistentGuaranteedComparer : IEqualityComparer<string>
{
public bool Equals(string x, string y)
{
return x == y;
}
public int GetHashCode(string obj)
{
if(obj == null)
return 0;
int hash = obj.Length;
for(int i = 0; i != obj.Length; ++i)
hash = (hash << 5) - hash + obj[i];
return hash;
}
}
그런 다음 내장 된 해시 코드 대신 이것을 사용하십시오.
우리가 그 반대를 원할 수있는 흥미로운 사례가 있습니다. 해싱하는 문자열 집합을 제어 할 수 있다면 동일한 해시 코드를 사용하여 여러 문자열을 선택할 수 있습니다. 해시 기반 컬렉션의 성능은 최악의 경우를 맞이할 것이고 매우 잔인 할 것입니다. 내가 처리 할 수있는 것보다 더 빨리이 작업을 수행 할 수 있으므로 서비스 거부 공격이 될 수 있습니다. 이런 일이 발생하는 경우는 많지 않지만 중요한 것은 전송하는 XML 문서를 처리하고 일부 요소를 배제 할 수 없다는 것입니다. 많은 형식으로 인해 요소 내에서 요소의 자유가 허용됩니다. 그런 다음NameTable
파서 내부가 다칠 것입니다. 이 경우 매번 새로운 해시 메커니즘을 만듭니다.
public class RandomComparer : IEqualityComparer<string>
{
private int hashSeed = Environment.TickCount;
public bool Equals(string x, string y)
{
return x == y;
}
public int GetHashCode(string obj)
{
if(obj == null)
return 0;
int hash = hashSeed + obj.Length;
for(int i = 0; i != obj.Length; ++i)
hash = hash << 5 - hash + obj[i];
hash += (hash << 15) ^ 0xffffcd7d;
hash ^= (hash >>> 10);
hash += (hash << 3);
hash ^= (hash >>> 6);
hash += (hash << 2) + (hash << 14);
return hash ^ (hash >>> 16)
}
}
이것은 주어진 사용 내에서 일관성이 있지만 사용에서 일관성이 없기 때문에 공격자는 강제로 DoSsed가되도록 입력을 구성 할 수 없습니다. 부수적으로,NameTable
~을 사용하지 않는다.IEqualityComparer<T>
필요한 경우를 제외하고는 문자열을 구성하지 않고 인덱스와 길이가있는 문자 배열을 처리하려고하기 때문에 비슷한 점이 있습니다.
덧붙여 말하면, 자바에서는string
가 지정되어 변경되지는 않지만 다른 클래스에서는 그렇지 않을 수 있습니다.
편집 : 촬영 한 접근 방식의 전반적인 품질에 대한 조사를 수행했습니다.ConsistentGuaranteedComparer
위와 같이, 나는 더 이상 내 알고리즘에 그러한 알고리즘을 사용하는 것에 만족하지 않는다. 개념을 설명하는 역할을하는 반면, 좋아할만한 배포를하지 못합니다. 물론, 이미 그런 것을 구현했다면 보증을 위반하지 않고 변경할 수는 없지만,이 내 서재는 연구 후에 쓰여졌다.다음과 같이
public class ConsistentGuaranteedComparer : IEqualityComparer<string>
{
public bool Equals(string x, string y)
{
return x == y;
}
public int GetHashCode(string obj)
{
return obj.SpookyHash32();
}
}
그것을 위해RandomComparer
위의 내용은 나쁘지는 않지만 개선 될 수도 있습니다.
public class RandomComparer : IEqualityComparer<string>
{
private int hashSeed = Environment.TickCount;
public bool Equals(string x, string y)
{
return x == y;
}
public int GetHashCode(string obj)
{
return obj.SpookyHash32(hashSeed);
}
}
또는 예측 가능성을 더욱 높일 수 있습니다.
public class RandomComparer : IEqualityComparer<string>
{
private long seed0 = Environment.TickCount;
private long seed1 = DateTime.Now.Ticks;
public bool Equals(string x, string y)
{
return x == y;
}
public int GetHashCode(string obj)
{
return obj.SpookyHash128(seed0, seed1).GetHashCode();
}
}
string.GetHashCode()
... "이제 .NET 소스를 사용할 수있게되었습니다.지금은 권위있는 출처를 가지고있다.그 (것)들은 몇몇 구조에있는 실제로 무작위 haschodes를 사용하는 것을 보여준다FEATURE_RANDOMIZED_STRING_HASHING
빌드 변수가 설정됩니다. 또한,DEBUG
그들은 또한 할 빌드hash1 ^= ThisAssembly.DailyBuildNumber;
해시 값을 유지하려고하는 것처럼 아무도 바보 같은 짓을하지 않게하려면, - Scott Chamberlain
그것의지동일한 기계에서도 다른 실행 결과를 낼 수 있습니다.
그래서 기본적으로 (그리고 실제로 사용되는)흐름프로그램을 실행하지만, 그것을 저장하기위한 의미가 없다. 네가 얻는 숫자가실행 시간.
편집하다
문자열의 특정 경우에 대해 기계가 다른 구조를 갖는 경우를 제외하고는 다른 기계에서도 동일한 결과를 생성합니다.