跳到主要内容

Swift中的Hashable

提示
  1. Swift 中的 Hashable 协议Hashable 协议为 Swift 对象提供 hashValue,用于比较实例的相等性。
  2. 比较实例的哈希值:通过实现 Hashable 协议,可以比较具有不同或相同属性值的实例的哈希值,以确定它们是否相等。
  3. 自定义哈希函数:可以通过定义 hash(into hasher: inout Hasher) 函数并使用 hasher.combine() 来指定比较的属性,以控制哈希值的生成。

在 Swift 中,Hashable 是一个协议,为我们的对象提供了 hashValuehashValue 用于比较两个实例。

要使用 hashValue,我们首先需要将类型(结构体、类等)与 Hashable 属性相符合(关联)。例如,

struct Employee: Hashable {
...
}

这里,我们已经使 Employee 结构体符合 Hashable 协议。

现在,当我们创建 Employee 的实例时,协议将为这些实例提供哈希值。

示例:Swift 可哈希协议(Hashable Protocol)

struct Employee: Hashable {
var name: String
}

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

// 打印哈希值
print(object1.hashValue)
print(object2.hashValue)

输出

754256748862435114
-6408043519205941253

这里,object1.hashValueobject2.hashValue 分别返回 object1object2 实例的哈希值。

注意:哈希值是一个长整数,根据您所使用的系统可能会有所不同,因此对于相同的代码,您可能会得到不同的值。

使用可哈希协议比较实例

// 使 Employee 符合 Hashable
struct Employee: Hashable {

var name: String
var salary: Int
}

// 初始化两个具有不同属性值的对象
let obj1 = Employee(name: "Sabby", salary: 40000)
let obj2 = Employee(name: "Cathy", salary: 30000)

print("不同的哈希值:")
print(obj1.hashValue)
print(obj2.hashValue)

// 初始化两个具有相同属性值的对象
let obj3 = Employee(name: "Lanny", salary: 50000)
let obj4 = Employee(name: "Lanny", salary: 50000)

print("\n相同的哈希值:")
print(obj3.hashValue)
print(obj4.hashValue)

输出

不同的哈希值:
3934953678767833906
4997634560615333199

相同的哈希值:
1588129438168529318
1588129438168529318

在上面的示例中,我们创建了一个名为 Employee 的结构体,该结构体符合 Hashable 协议。

我们创建了两个对象 obj1obj2

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

在这里,两个实例的属性 namesalary 都有不同的值。这就是为什么 obj1obj2 的哈希值不同的原因。

类似地,我们又创建了两个对象。

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

这一次,obj3 和 obj4 的属性值相同,所以我们得到了相同的实例哈希值。

哈希函数和 Combine

在上面的示例中,我们比较了结构体的所有属性。

然而,有时我们可能只想比较类型的选定属性。在这种情况下,我们可以在类型内使用哈希函数。例如,

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

这里,hash() 函数使用 hasher.combine() 来指定我们想要比较的属性。

使用哈希函数

struct Employee: Hashable {

var name: String
var salary: Int

// 创建一个 hash() 函数来只比较 age 属性
func hash(into hasher: inout Hasher) {
hasher.combine(salary)
}

}

// 使用不同的 salary 属性值初始化两个对象
let obj1 = Employee(name: "Sabby", salary: 349879)
let obj2 = Employee(name: "Sabby", salary: 422532)

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

输出

3932232896576771782
743881919875172951

在上述示例中,我们使用了 hash() 函数基于 salary 属性比较两个实例。

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

这里,ob1obj2 的工资不同,所以我们得到了不同的哈希值。

如果我们在 hash() 函数内使用了 name 属性,我们将得到相同的哈希值。这是因为两个对象的 name 属性是相同的。

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

// 输出:
// 976332112043722041
// 976332112043722041