Hashable Protocol
In Swift, a Hashable is a protocol that provides a hashValue
to our object. The hashValue
is used to compare two instances.
Many types in the standard library conform to Hashable
: Strings, integers, floating-point and Boolean values, and even sets are hashable by default.
It is an essential part of hash-based collections like sets and dictionaries. Conforming to the Hashable
protocol allows instances of a custom type to be used as keys in dictionaries or elements in sets.
The Hashable
protocol requires you to implement a single property called hashValue
or a function called hash(into:)
that returns a unique integer value for each instance of the type. This integer value is used to determine the location of the element in the collection.
Hashable protocol inherited by Equatable protocol
Example 1:
Consider a GridPoint
type that describes a location in a grid of buttons. Here’s the initial declaration of the GridPoint
type:
/// A point in an x-y coordinate system.
struct GridPoint {
var x: Int
var y: Int
}
You’d like to create a set of the grid points where a user has already tapped. Because the GridPoint
type is not hashable yet, it can’t be used in a set. To add Hashable
conformance, provide an ==
operator function and implement the hash(into:)
method.
extension GridPoint: Hashable {
static func == (lhs: GridPoint, rhs: GridPoint) -> Bool {
return lhs.x == rhs.x && lhs.y == rhs.y
}
func hash(into hasher: inout Hasher) {
hasher.combine(x)
hasher.combine(y)
}
}
The hash(into:)
method in this example feeds the grid point’s x
and y
properties into the provided hasher. These properties are the same ones used to test for equality in the ==
operator function.
Now that GridPoint
conforms to the Hashable
protocol, you can create a set of previously tapped grid points.
Now that GridPoint
conforms to the Hashable
protocol, you can create a set of previously tapped grid points.
var tappedPoints: Set = [GridPoint(x: 2, y: 3), GridPoint(x: 4, y: 1)]
let nextTap = GridPoint(x: 0, y: 1)
if tappedPoints.contains(nextTap) {
print("Already tapped at (\(nextTap.x), \(nextTap.y)).")
} else {
tappedPoints.insert(nextTap)
print("New tap detected at (\(nextTap.x), \(nextTap.y)).")
}
// Prints "New tap detected at (0, 1).")
Example 2:
struct Person: Hashable {
let name: String
let age: Int
}
let person1 = Person(name: "John Doe", age: 30)
let person2 = Person(name: "Jane Doe", age: 25)
let people = Set([person1, person2])
if people.contains(person1) {
print("Person 1 is in the set")
} else {
print("Person 1 is not in the set")
}
In this example, the Person
struct conforms to the Hashable protocol. This means that the Person
struct can be used as the key in a dictionary or as an element in a set.
Example 3: Hashable protocol key in a dictionary:
struct Book: Hashable {
let title: String
let author: String
}
let book1 = Book(title: "The Hunger Games", author: "Suzanne Collins")
let book2 = Book(title: "The Hitchhiker's Guide to the Galaxy", author: "Douglas Adams")
let books = [book1: "Book 1", book2: "Book 2"]
print(books[book1]) // "Book 1"
In this example, the Book
struct conforms to the Hashable protocol. This means that the Book
struct can be used as the key in a dictionary. The books
dictionary uses the title
and author
properties of the Book
struct as the keys.
Please like and follow if you like my article, it motivates me to continue….