Hash Value
Hash Value 는
데이터를 간단한 숫자로 변환한 것이다.
원본 데이터를 특정 규칙에 따라 처리하여
간단한 숫자로 만든 것을 해쉬값이라고 한다.
2개의 데이터를 비교할 때,
데이터가 동일하면 각 데이터의 해쉬값도 동일하다.
데이터가 조금이라도 달라진다면,
완전히 다른 해쉬값을 가진다.
// example1
let greeting: String = "Hello!"
let hi: String = "Hello!"
let one: String = "1"
print(one.hashValue) // 8067371448109303382
print(two.hashValue) // 8067371448109303382
print(three.hashValue) // 5046920956587776301
"Hello!"
를 담고 있는
상수 greeting
과 hi
의 해쉬값은 동일하다.
"1"
을 담고 있는
상수 one
은 다른 상수들과 해쉬값이 다르다.
동일한 데이터는 해쉬값이 동일하다는 것을 확인할 수 있다.
하지만,
2개의 서로 다른 데이터가 동일한 해쉬값을 가질 때도 있다.
데이터의 양은 무한하고,
해쉬값은 일정 크기의 Int 값이므로 유한하기 때문이다.
그렇기 때문에, 해쉬 충돌 [ Hash Collision ] 이 발생한다.
해쉬 충돌은 다른 데이터 구조를 사용하여 해결할 수 있다.
(연결리스트, 선형조사법 등)
Hashable
Hashable 한 타입의 데이터는
해쉬값 [ Hash Value ] 를 구할 수 있다.
// example2
// 구조체 Drink 는 Hashable Protocol 을 준수한다.
struct Drink: Hashable {
let name: String
let mainIngredient: String
let alcohol: Double
}
let lemonade = Drink(name: "lemonade",
mainIngredient: "lemon",
alcohol: 0.0
)
let strawberryade = Drink(name: "strawberryade",
mainIngredient: "strawberry",
alcohol: 0.1
)
// Hashable Protocol 을 준수하므로,
// 두 인스턴스를 == 연산자로 비교할 수 있다.
if lemonade == strawberryade {
print("lemonade: \(lemonade.hashValue)\n
strawberryade: \(strawberryade.hashValue)\n
Same!")
} else {
print("lemonade: \(lemonade.hashValue)\n
strawberryade: \(strawberryade.hashValue)\n
Different!")
}
// lemonade: 2846229625861066617
// strawberryade: -3846330515821480395
// Different!
원래라면 구조체 Drink
는
두 인스턴스를 ==
연산자로 비교할 수 없을 것이다.
Hashable Protocol 을 준수하기 때문에,
두 인스턴스를 비교할 수 있고,
hashValue
프로퍼티를 통해
해쉬값을 확인할 수 있었다.
Swift 에서
Set 타입의 값, Dictionary 타입의 Key 는 Hashable 해야 하고,
기본 타입인 String, Int 등은 자동으로 Hashable 하다.
해쉬값을 사용하는 이유는
속도가 빠르기 때문이다.
해쉬 테이블에서는 해쉬값을 index 로 사용하여
원하는 값의 위치를 한 번에 알 수 있기 때문에,
일반적인 방법인 처음부터 순서대로 찾는 것보다 빠르다.
📚 Reference
[Swift] Hashable 해야 한다? 해쉬값이란? (간단 요약)