博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
isEqual
阅读量:6947 次
发布时间:2019-06-27

本文共 3266 字,大约阅读时间需要 10 分钟。

== 基本类型
== 对象 对象的地址
[UIColor redColor]; // 会都相等 可能是一个全局静态变量UIColor *color1 = [UIColor colorWithRed:0.5 green:0.5 blue:0.5 alpha:1.0];UIColor *color2 = [UIColor colorWithRed:0.5 green:0.5 blue:0.5 alpha:1.0];NSLog(@"color1 == color2 = %@", color1 == color2 ? @"YES" : @"NO");NSLog(@"[color1 isEqual:color2] = %@", [color1 isEqual:color2] ? @"YES" : @"NO");复制代码
color1 == color2 = NO[color1 isEqual:color2] = YES复制代码
== 简单的判断是否是同一个对象
isEqual 判断对象是否相同

对于对象来说,==判断指针地址是否相同。如果指针地址相同,肯定是同一对象,isEqual肯定也相同,但是isEqual相同,==不一定相同

如何重写自己的isEqual方法

常见类型的isEqual方法还有NSString isEqualToString / NSDate isEqualToDate / NSArray isEqualToArray / NSDictionary isEqualToDictionary / NSSet isEqualToSet, 很多人在iOS开发中, 都是这么重写hash方法的

- (NSUInteger)hash {    return [super hash];}复制代码

这样写有问题么? 带着这个问题, 我们先来看下[super hash]的值到底是什么

Person *person = [[Person alloc] init];NSLog(@"person = %ld", (NSUInteger)person);NSLog(@"[person1 getSuperHash] = %ld", [person getSuperHash]);复制代码

打印结果如下

person = 140643147498880[person1 getSuperHash] = 140643147498880复制代码

由此可以看出, [super hash]返回的就是该对象的内存地址

联想到前面对hash值唯一性的要求, 使用对象的内存地址作为hash值不是很好么?

别急, 我们添加如下两个对象到NSSet中试试

Person *person1 = [Person personWithName:kName1 birthday:self.date1];Person *person2 = [Person personWithName:kName1 birthday:self.date1];NSLog(@"[person1 isEqual:person2] = %@", [person1 isEqual:person2] ? @"YES" : @"NO");NSMutableSet *set = [NSMutableSet set];[set addObject:person1];[set addObject:person2];NSLog(@"set count = %ld", set.count);复制代码

此时打印结果如下

[person1 isEqual:person2] = YESset count = 2复制代码

isEqual相等的两个对象都加入到了NSSet中(set count = 2), 所以直接返回[super hash]是不正确的

那么hash方法的最佳实践到底是什么呢?

大神Mattt Thompson在Equality中给出的结论就是

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

对于上面Person类的hash方法实现如下

- (NSUInteger)hash {    return [self.name hash] ^ [self.birthday hash];}复制代码
正确写法
@interface Person : NSObject@property (nonatomic, copy) NSString *name;@property (nonatomic, strong) NSDate *birthday;@end复制代码
- (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;}复制代码
  1. ==运算符判断是否是同一对象, 因为同一对象必然完全相同

  2. 判断是否是同一类型, 这样不仅可以提高判等的效率, 还可以避免隐式类型转换带来的潜在风险

  3. 通过封装的isEqualToPerson方法, 提高代码复用性

  4. 判断person是否是nil, 做参数有效性检查

  5. 对各个属性分别使用默认判等方法进行判断

  6. 返回所有属性判等的与结果

hash方法只在对象被添加至NSSet和设置为NSDictionarykey时会调用

  • NSSet添加新成员时, 需要根据hash值来快速查找成员, 以保证集合中是否已经存在该成员

  • NSDictionary在查找key时, 也利用了key的hash值来提高查找的效率 用作 NSMutableDictionary 中的 key 时,hash 方法执行了,不过崩溃了,因为 Model 类没有实现 NSCopying 协议

hash方法与判等的关系?

hash方法主要是用于在Hash Table查询成员用的, 那么和我们要讨论的isEqual()有什么关系呢?

为了优化判等的效率, 基于hash的NSSet和NSDictionary在判断成员是否相等时, 会这样做

Step 1: 集成成员的hash值是否和目标hash值相等, 如果相同进入Step 2, 如果不等, 直接判断不相等

Step 2: hash值相同(即Step 1)的情况下, 再进行对象判等, 作为判等的结果

简单地说就是

hash值是对象判等的必要非充分条件

转载于:https://juejin.im/post/5c1a55f6518825314b0beb1b

你可能感兴趣的文章
PHP开发APP接口
查看>>
功能测试报告
查看>>
获取手机联系人信息
查看>>
关于64位操作系统,应用程序占用内存飙升的问题解决方法记录
查看>>
Quartz.NET 调度配置说明
查看>>
统计Redis中各种数据大小
查看>>
JFinal-Beetl-Shiro(JdbcRealm)-例子
查看>>
java中的内部类总结
查看>>
跬步之积,以至千里
查看>>
Windows和Linux设计和原理哪个系统更先进呢?
查看>>
1234
查看>>
原 shell学习四运算符
查看>>
var与Javascript变量隐式声明
查看>>
InstallShield安装包中集成第三方安装包的方案选择
查看>>
windows下 sublime text2 跳转查看go源码
查看>>
c语言中的面向对象(1)----kobject 和 container_of
查看>>
单利模式
查看>>
kafka client使用kerberos
查看>>
修复ThinkPad一键恢复功能
查看>>
HowTo: Linux / UNIX List Just Directories Or Di...
查看>>