iOS hash函数与isEqual方法思考

2018-06-26  本文已影响35人  Rokkia

说到hash函数,我们就需要了解一下Hash表,那么什么是hash表呢,在我的理解就是一个数组。通过hash函数将字符串等元素转换成一串数字,将这串数字与数组的长度取余当做数组的下标。对应的数组空间来存储这个元素。这样做有什么好处呢,好处在于我们可以使用O(1)的速度来获取到某一个值。 关于hash的理解可以看一下这篇文章 深入理解哈希表

存储基本可以分为下面是哪个步骤(这段话来自于上面的那篇文章,很好的总结了存储过程):

  1. 根据 key 计算出它的哈希值 h。
  2. 假设箱子的个数为 n,那么这个键值对应该放在第 (h % n) 个箱子中。
  3. 如果该箱子中已经有了键值对,就使用开放寻址法或者拉链法解决冲突。

拉链法hash表的样子就会变成类似这样。


拉链法hash表(图片来自网络).png

OK, 基础已经铺垫完成,让我们来看一下iOS中的使用。当我们去比较两个两个对象是否相等的时候,我们无法使用 == 来比较,原因很简单,当我们使用 == 来比较两个对象的时候,我们比较的是两个对象的内存地址,这样一来肯定无法比较。这里参考文章iOS开发之不要告诉我你真的懂isEqual与hash!
于是,当我们想去比较两个对象是否相等的时候,我们需要重写isEqual方法。

-(BOOL)isEqual:(id)object{
    if (self == object) {
        return YES;
    }
    if (![self isKindOfClass:[RokkiaNetWorking class]]) {
        return NO;
    }
    return [self isEqualToRokkiaNetWorking:(RokkiaNetWorking *)object];
}
-(BOOL)isEqualToRokkiaNetWorking:(RokkiaNetWorking *)object{
    if (!object) {
        return NO;
    }
    BOOL isNameEqual = //比较
    BOOL isHttpEqual = //比较
    return isNameEqual && isHttpEqual;
}

当我们实验的时候,你会发现很完美,但是我们为什么还要使用重写hash函数呢。
当我们使用NSSet的时候,我们会发现当我们传入两个isEqual为True的对象时,我们拿到的set count = 2,因为我们会将每个对象的地址进行hash所以得到的地址会是两个,作为isEqual的对象set中我们无需存储两边。所以我们可以重写hash方法。

In reality, a simple XOR over the hash values of critical properties is sufficient 99% of the time(对关键属性的hash值进行位或运算作为hash值)

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

猜你喜欢

热点阅读