iOS 底层系列 - isEqual与hash

1,421 阅读1分钟

什么时候需要重写isEqual方法 和 hash方法

isEqual:

  • 当你的子类之间需要判断相等时,重写isEqual:方法

hash 方法:

  • 如果你写的子类还需要添加到集合类型(NSDictionary,NSSet等)中去,hash方法也需要重写。

内部实现

- (BOOL)isEqual:(id)object {
    if (self == object) {
        return YES;
    }
    if (![object isKindOfClass:[Person class]]) {
        return NO;
    }
    return [self isEqualToPerson:(Person *)object];
}


- (BOOL)isEqualToPerson:(Person *)person {
    if (!person) {
        return NO;
    }
    BOOL haveEqualNames = (!self.name && !person.name) || [self.name isEqualToString:person.name];
    BOOL haveEqualBirthdays = (!self.birthday && !person.birthday) || [self.birthday isEqualToDate:person.birthday];
    return haveEqualNames && haveEqualBirthdays;
}


- (NSUInteger)hash {
  return [self.name hash] ^ [self.birthday hash];
}

== 和 isEqual 和 isEqualToString 的区别

  1. ==
    • 比较两个对象的指针,若是字符串 对比的是首地址。
  2. isEqualToString
    • 比较两个字符串的内容.
  3. isEqual:
    • 默认情况下是比较两个对象的内存地址.
    • 系统自带的类(NSString, NSArray 等)重写了这个方法,改变了这个方法的判断规则。 (一般改为比较两个对象的内容,不是内存地址)

为什么要有isEqual方法?

== 运算符只是简单地判断是否是同一个对象。

isEqual方法可以判断对象是否相同, 例如UIColor对象表示的color是否相同。

例子:

isEquel和hash的关系

重写对象的isEquel和Hash方法,在Hash方法中返回对象属性位运算符的hash值,在 isEquel方法中比较对象的hash值。

这样可以确保在NSSet这样的集合中,对象是否一致用对象属性hash NSDictionary值进行判断。

- (NSUInteger)hash{
    return self.age.hash ^ self.name.hash;
}

- (BOOL)isEqual:(id)object{
    return self.hash == [object hash];
}

Hash 方法在什么时候会被调用

Hash方法只在对象被添加至NSSet和设置NSDictionary的key时会调用.

NSSet 添加新成员时, 需要根据hash值来快速查找成员, 以保证集合中是否已经存在该成员 NSDictionary在查找key时, 也利用了key的hash值。