Walidelzo
Walidelzo

Reputation: 11

What does Hash Values for Set Types in swift?

when i read swift documentation i can not understand what that mean?. A type must be hashable in order to be stored in a set—that is, the type must provide a way to compute a hash value for itself. A hash value is an Int value that is the same for all objects that compare equally, such that if a == b, it follows that a.hashValue == b.hashValue.

Upvotes: 0

Views: 1464

Answers (1)

vacawama
vacawama

Reputation: 154513

Sets are designed for performance. The contains(_:) method on Set is O(1) complexity meaning it takes a constant amount of time to perform no matter the size of the set. contains(_:) on an Array is O(n) meaning the time to determine if the array contains an element increases as the size of the array increases.

How does a Set do that? It uses a hashValue for the items of the Set and contains an internal dictionary like structure that maps the hashValue to the list of items with that hashValue. This makes testing equality of complex structures (like String) very quick because Set first tests if two values have the same hashValue. If the hashValues are different, it doesn't need to check the contents of the structs themselves.

To test if the Set contains a value, it is necessary to only look up the hashValue in the dictionary and then compare the item to the values that match.

So, for items to be contained in a Set, it is important to provide a hashing function that:

  1. Is the same if two structs/objects are equal. (absolute requirement)
  2. Computes a wide range of hashValues so that the items are widely distributed and don't require falling back to the slower check for equality. (for good performance)

Here is an example of a Hashable struct that is appropriate for storage in a Set:

struct Option: Hashable, CustomStringConvertible {
    var title: String
    var key: String
    var value: Int
    var description: String { return "{title: \"\(title)\", key: \"\(key)\", value: \(value)}" }

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

    static func ==(lhs: Option, rhs: Option) -> Bool {
        return lhs.title == rhs.title && lhs.key == rhs.key
    }
}

Note: In this example, only the title and key properties are considered for equality. Two structs can be equal even if they have different value properties. The hash(into:) function likewise only considers the title and key properties.

Upvotes: 5

Related Questions