包含覆盖isEqual的对象的NSSet

时间:2015-07-14 15:49:12

标签: objective-c cocoa cocoa-touch nsset

在我的班级中,我会覆盖isEqual

@interface MyClass : NSObject

@property (nonatomic, strong) NSString * customID;

@end

我覆盖了isEqual,因此只检查customID

的相等性
- (BOOL)isEqual:(id)object {

    if ([object isKindOfClass:[MyClass class]]) {
        if (self.customID == nil) {
            return NO;
        }
        return [self.customID isEqual:[object customID]];
    }
    return [super isEqual:object];
}

现在NSSet实际上是一个哈希表,如果它包含一个哈希值,那么可以快速检查...这就是我们所知道的事情

但是,让我们想象一下这段代码

NSArray * instancesToCheck = ...;
NSArray * allInstances = ...;

for (MyClass * instance in allInstances) {

    if ([instancesToCheck containsObject:instance]) {
        // do smth
    }

}

我想用这个“优化”(使用NSSet进行成员资格测试)

NSArray * instancesToCheck = ...;
NSArray * allInstances = ...;

NSSet * instancesToCheckAsSet = [NSSet setWithArray:instancesToCheck];

for (MyClass * instance in allInstances) {

    if ([instancesToCheckAsSet containsObject:instance]) {
        // do smth
    }

}

第二个代码是否提供任何性能优势(假设在创建它的数组中没有重复,并且instancesToCheck包含不同的指针,但是一些对象具有相同的customID,使isEqual == YES但指针比较==否)?

当我查找文档时,我发现,containsObject调用isEqual,所以它必须遍历所有对象

将NSSet与对象一起使用会有什么影响,覆盖isEqual?那么NSSet效率会降低吗?

2 个答案:

答案 0 :(得分:2)

  

第二个代码是否提供了所有性能优势

绝对。数组必须在数组中循环检查每个对象。一个集合或多或少知道即时是否包含对象,因为它是一个哈希表。实际上,这类事物恰好是 for 的集合。

答案 1 :(得分:1)

你必须覆盖hash,否则覆盖isEqual:否则可能会破坏功能,而事情可能无法按预期运行

两个被认为是"相等的对象"必须返回相同的哈希值。

- (BOOL)isEqual:(id)object {

    if ([object isKindOfClass:[MyClass class]]) {
        if (self.customID == nil) {
            return NO;
        }
        return [self.customID isEqual:[object customID]];
    }
    return [super isEqual:object];
}

// MUST overwrite hash

- (NSUInteger)hash {
    return [self.customID hash];
}