2.7 KiB
数组、集合、字典与 hash、isEqual 方法的关联
-
NSArray 允许重复添加元素,添加元素的时候不查重,所以不会调用上面2个方法。在移出元素的时候会依次遍历数组内的元素,每个元素调用 isEqual 方法(remove 方法传入的元素作为参数),所有返回真值的元素都会被移除。在字典中不涉及 hash 方法。
-
NSSet 不允许重复添加元素,所以在添加新元素的时候,该元素的 hash 方法会被调用,若集合中不存在与此元素 hash 相同的元素,则它会被直接加入集合,不调用 isEqual 方法;若存在,则依次调用该集合每个元素的 isEqual 方法,返回真值则判等,不加入,处理结合,若返回 false, 则判定集合内不存在该元素,将其加入。
-
集合中移除元素时,首先调用它的 hash方法,若集合中存在与其 hash值 相等的元素,则调用该元素的 isEqual方法,若返回真值则判断,进行移除;若不存在,则会依次调用集合中每个元素的 isEqual方法,只要找到一个返回真值的元素,就进行移除,并结束整个过程(所有这样会有其它满足 isEqual 方法但却漏掉未被删除的元素)。调用 contains 方法时类似
-
因此如果自定义对象被加入到集合或作为字典的 key 时,需要同时重写 isEqual 方法和 hash 方法,这样,若集合存在某元素,则调用它的 contains 和 remove 方法时,可以在 O(1) 完成查询,否则需要 O(n) 完成。
-
需要注意的是,NSDictionary 的 key、value 都说对象类型即可,但是被设为 key 的对象需要遵循 NSCopying 协议。
-
hash 方法出现的目的是:当我们从数组中查找元素时,需要依次遍历数组中的元素,时间复杂度为 O(n),为了解决效率问题,引入了 Hash Table 方法。当添加元素的时候,为每个元素设置了 hash 值,这样当下次查找的时候就直接通过 hash 值找到对应的位置,时间复杂度为 O(1)。设计一个合理的 hash 算法的指标是对于每个参数,其返回的 hash 值唯一。
-
查阅资料可知,一个推荐的自定义对象的 hash 算法是将关键属性的 hash 值,按照位或运算
@interface Person : NSObject
@property (nonatomic, strong) NSString *name;
@property (nonatomic, strong) NSDate *birthday;
@end
- (NSUInteger)hash{
return [self.name hash] ^ [self.birthday hash];
}
- NSObject 类中的 equal 方法的判断是包括内存地址的,也就是说,NSObject 若想判断2个对象相等,那么这2个对象的内存地址必须相等