2015-07-14 3 views
-1

В моем классе я перезаписать IsEqualNSSet, содержащие объекты с перезаписан 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 
    } 

} 

Имеет ли второй код обеспечить любой выигрыш в производительности на всех (в предположении, что существует нет дубликатов в массиве, из которого он был создан, а экземплярыToCheck содержат разные указатели, но некоторые объекты имеют один и тот же идентификатор, что делает isEqual == YES, но сравнение указателей == NO)?

Когда я посмотрел на документы, я обнаружил, что containsObject называет IsEqual, поэтому он должен перебрать все объекты в любом случае

Каковы последствия производительности при использовании NSSet с объектами, что перезаписать isEqual? Становится ли NSSet менее эффективным?

+1

FYI - если вы переопределите 'isEqual:' вы также должны переопределить 'hash'. Два объекта, которые считаются «равными», должны возвращать одно и то же значение хэш-функции. – rmaddy

ответ

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]; 
} 
1

ли второй код обеспечить любой выигрыш в производительности на всех

Абсолютно. Массив должен циклически проходить через массив, проверяющий каждый объект. Набор знает более или менее мгновенно ли объект содержится, потому что это хэш-таблица. Действительно, такого рода вещи - именно то, что набор для.

+0

в порядке, но если вы посмотрите на вопрос более внимательно, чем содержит вызовы oEject, isEqual, значит, он все равно должен перебирать все объекты, так как я не перезаписываю хэш (хэш по умолчанию - это адрес памяти?) –

+1

Ну, вы _should_ перезаписать хеш. Они идут вместе. Предполагается, что два объекта равны тогда и только тогда, когда их хэш-значения равны. Вы нарушите набор, если вы не подчиняетесь этому правилу. – matt

Смежные вопросы