NSSet 去重技巧:判断自定义类的相等

问题缘起

Set 有个天然属性,就是放入的元素不能重复,这个特性也被常用于去除重复数据:

var set:Set = ["1", "2", "3", "4", "1", "1"]
print("set:\(set)") //输出为:set:["2", "1", "3", "4"]

系统类可以很方便地放入Set,那么自定义类呢?
假设需要自定义Person类,有个name属性,这里我们假设名字相同的人只有一个,所以逻辑上name相同的对象,在Set中只能有一个,但对于对象来说,两个实例是不同的指针,是不同的:

class Person {
    var name:String
    init(name:String) {
        self.name = name
    }
}
var x1:Person? = Person(name:"Xishi")
var x2:Person? = Person(name:"Xishi")
var set:Set = [x1, x2]

实际上,以上代码无法通过编译:

'Set' requires that 'Person' conform to 'Hashable'

解决方案

Swift 要求放入Set的类实现Hashable 协议,而Hashable本身又继承了Equatable协议,所以这里要同时实现两个协议:

class Person : Hashable {
    var name:String
    init(name:String) {
        self.name = name
    }

    public var hashValue : Int {
        get {
            return self.name.hashValue
        }
    }

    static func ==(lhs: Person, rhs: Person) -> Bool {
        return lhs.name == rhs.name
    }
}
  • public var hashValue : Int是Hashable协议要求的,需要返回能代表对象的哈希值,这里正好利用 String 的哈希值。
  • 看起来怪怪的static func ==(lhs: Person, rhs: Person) -> Bool方法声明是运算符重载,这里把==当作方法名就好理解了,相当于替换了一个名叫==的方法。

这样,放入Set后,就能正常去除重复对象了。

小实验

== 方法改为固定返回 false,看看会发生什么,与你想象中一样吗?

你可能感兴趣的:(NSSet 去重技巧:判断自定义类的相等)