Strings, integers, floating-point, Boolean values, sets이 기본적으로 Hash Value를 제공합니다.
(set은 Hashable한 것 만 들어갈 수 있어요)
자신만의 사용자 정의 타입도 hash가 가능할 수 있습니다.
associated values없이 열거형(enum)을 정의하면, Hashable 준수가 자동으로 적용되고, hashValue프로퍼티를 추가하여 사용자 정의 타입에 Hashable 준수를 추가할 수 있습니다. (Swift4.1에서는 안해도 되지..)
타입의 hashValue프로퍼티에 의해 제공되는 hash 값은, 동일하게 비교되는 임의의 두 인스턴스에 대해 동일한 정수입니다.
즉, 같은 타입의 인스턴스인 a와 b의 경우, a==b이면 a.hashValue == b.hashValue입니다.
반대의 경우는 true가 아닐 수 있습니다. 동일한 hash 값을 가진 두개의 인스턴스가 서로 동일한 필요는 없습니다.
※ 중요 : hash값은 프로그램 실행에 따라 동일하지 않을 수도 있습니다. 향후 실행에 사용할 hash값을 저장하지 마십시오.
Conforming to the Hashable Protocol
자..위에서 Set은 Hashable한 것만 들어 갈 수 있고, Dictionary의 Key역시 Hashable한다고 그랬죠?
사용자 정의 타입을 Set에 넣거나 Dictionary Key로 만들고 싶으면, 타입이 Hashable을 준수하면 됩니다.
사용자 정의 타입의 Hashable과 Equatable 요구사항은 타입이 다음 조건을 충족시킬 때 컴파일러에서 자동으로 합성?(synthesized)해줍니다.
- 구조체의 경우, 저장프로퍼티는 모두 Hashable을 준수해야합니다.
- 열거형의 경우, 모든 associated values은 모두 Hashable을 준수해야합니다. (associated values가 없는 열거형은 정의 없이(hashValue말하는듯) Hashable을 준수합니다.)
타입의 Hashable준수를 커스터마이즈하거나, 위에서 말한 기준에 맞지 않는 형식으로 Hashable을 채택하거나, 또는 이미 존재하는 타입을 Hashable을 준수하도록 확장하는 경우에는 사용자 지정 타입에 hashValue 프로퍼티를 구현합니다. 타입이 Hashable 및 Equatable 프로토콜의 의미론적 요구사항(semantic requirements....이게 해석이 맞나)을 충족시키려면, 타입의 Equatable준수를 사용자 정의하여 일치시키는 것이 좋습니다.
예를들어, 버튼 그리드의 위치를 설명하는 GridPoint타입을 고려해보십시오. 다음은 GridPoint의 초기선언입니다.
/// A point in an x-y coordinate system.structGridPoint{
var x: Intvar y: Int
}
생각해보면, Swift의 Set과 Dictionary는 Array와 다르게 “순서”가 없죠? 그렇기 때문에 이 두 Collection이 Hashable과 관련이 있는 것 같아요..!
(추측임)
Hashable의 정의가 "정수 Hash 값을 제공하는 타입입니다.”라고 그랬죠? 이 정수 Hash(=hashValue)가 있기 때문에 우리가 찾으려는 원소?..를 빨리 찾을 수 있는 것이죠.
예를들어 0 ~ 10000까지 데이터를 담을 수 있는 리스트를 생성하고, “Zedd”에 Hash함수를 적용했습니다. Hash함수에 의해 나오는 값이 바로 Hash값이라고 그랬죠? 근데 이게 음..100이 나왔어! 그럼 인덱스 100에 “Zedd”를 저장합니다. Hash함수는 동일한 인풋에는 동일한 아웃풋이 나오므로 만약에 나중에 또 “Zedd”가 들어와요 그럼 ㅇㅇ너 100으로 가셈. 그러고보니 Set과 Dictionary가 중복을 허락하지 않는 이유도 Hash때문이라고 할 수 있겠네요.
그럼 제가 이제 “Zedd”를 찾으려고 하면 Hash함수는 또 Hash값으로 100을 리턴할테고, 나는 앞에서부터 찾을 필요 없이 걍 인덱스 100으로 가면 “Zedd”를 찾을 수 있는 것이죠. 뭐 인덱스가 충돌하고 어쩌고 그런것도 있는데, 그럴때는 해결방법이 여러가지가 있다고는 하는데..제가 배웠던건 비어있는 인덱스가 나올 때 까지 어떤 알고리즘 하나 더 돌려서 2차 Hash값을 구하는? 그런거였어요 :) 이거는 찾아보시면 될듯.