Swift Hashable

In Swift, a Hashable is a protocol that provides a hashValue to our object. The hashValue is used to compare two instances.

To use the hashValue, we first have to conform (associate) the type (struct, class, etc) to Hashable property. For example,

struct Employee: Hashable {
  ...
}  

Here, we have conformed the Employee struct to the Hashable protocol.

Now when we create instances of Employee, the protocol will provide hash values to the instances.


Example: Swift Hashable Protocol

struct Employee: Hashable {
  var name: String
}

let object1 = Employee(name: "Sabby")
let object2 = Employee(name: "Smith")

// print hash values
print(object1.hashValue)
print(object2.hashValue)

Output

754256748862435114
-6408043519205941253

Here, object1.hashValue and object2.hashValue returns hash values for instances object1 and object2 respectively.

Note: A hash value is a long integer that varies based on the system you are using, so you might get different values for the same code.


Compare Instances using Hashable Protocol

// conform Employee to Hashable
struct Employee: Hashable {
    
    var name: String
    var salary: Int
}

// initialize two objects with different property values 
let obj1 = Employee(name: "Sabby", salary: 40000)
let obj2 = Employee(name: "Cathy", salary: 30000)

print("Different hash value: ")
print(obj1.hashValue)
print(obj2.hashValue)

// initialize two objects with same property values 
let obj3 = Employee(name: "Lanny", salary: 50000)
let obj4 = Employee(name: "Lanny", salary: 50000)

print("\nSame hash value: ")
print(obj3.hashValue)
print(obj4.hashValue)

Output

Different hash value: 
3934953678767833906
4997634560615333199

Same hash value: 
1588129438168529318
1588129438168529318

In the above example, we have created a struct named Employee that conforms to the Hashable protocol.

We have created two objects obj1 and obj2.

let obj1 = Employee(name: "Sabby", salary: 40000)
let obj2 = Employee(name: "Cathy", salary: 30000)

Here, both instances have different values for properties name and salary. That's why hash values for obj1 and obj2 are different.

Similarly, we have created two more objects.

let obj3 = Employee(name: "Lanny", salary: 50000)
let obj4 = Employee(name: "Lanny", salary: 50000)

This time properties values for obj3 and obj4 are the same, so we get the same hash values for the instances.


Hash Function and Combine

In the above example, we have compared all the properties of the struct.

However, sometimes we may want to compare selective properties of the type. In this case, we may use the hash function inside the type. For example,

func hash(into hasher: inout Hasher) { 
  hasher.combine(name)
}

Here, the hash() function uses hasher.combine() to specify the property that we want to compare.


Use of Hash Function

struct Employee: Hashable {
  
 var name: String
 var salary: Int

 // create a hash() function to only compare  age property        
 func hash(into hasher: inout Hasher) {
   hasher.combine(salary)
 }

}

// initialize two objects with different values for salary property
let obj1 = Employee(name: "Sabby", salary: 349879)
let obj2 = Employee(name: "Sabby", salary: 422532)

print(obj1.hashValue)
print(obj2.hashValue)

Output

3932232896576771782
743881919875172951

In the above example, we have used the hash() function to compare two instances on the basis of the salary property

func hash(into hasher: inout Hasher) { 
  hasher.combine(salary)
}

Here, the salary of ob1 and obj2 are different, so we get different hash values.

If we have used the name property inside the hash() function, we will get the same hash value. This is because name of both objects are the same.

func hash(into hasher: inout Hasher) { 
  hasher.combine(age)
}

// Output:
// 976332112043722041
// 976332112043722041
Did you find this article helpful?