NSOrderedSet vs NSArray indexOfObjectPassingTest:
Обзор ссылок на классы NSOrderedSet гласит:
Упорядоченные наборы можно использовать в качестве альтернативы массивам, когда важен порядок элементов, и производительность при проверке того, содержится ли объект в наборе, является соображением - проверка на принадлежность массива выполняется медленнее, чем проверка на принадлежность к набору.
Какие методы считаются "тестированием на членство"? Просто containsObject:
? Или будет indexOfObjectPassingTest:
также быть быстрее?
Я спрашиваю, потому что, если бы я просто имел идентификатор объекта (например, с сервера) и хотел бы проверить, содержит ли упорядоченный набор объект с таким идентификатором, я бы использовал indexOfObjectPassingTest:
, Но этот метод, поскольку он проверяет каждый объект в коллекции, кажется, что он будет таким же медленным, как и для массива. С другой стороны, containsObject:
кажется, что это будет быстрее, так как он использует в своих интересах NSObject
методы hash
& isEqual:
, Я мог бы просто создать объект исследования с идентификатором, который у меня есть, а затем использовать containsObject:
, Но затем, если упорядоченный набор уже содержит объект с этим идентификатором, я просто откажусь от тестового объекта и обновлю свойства объекта, уже находящегося в упорядоченном наборе. Это кажется дополнительной работой, чтобы сначала создать объект исследования. В таком случае стоит ли использовать упорядоченный набор над массивом?
Кроме того, я бы сортировал объекты по дате, а не по идентификатору.
Я бы использовал NSMutableDictionary
с привязкой идентификаторов объектов к объектам, как предложил St3fan, но я также хочу отображать объекты в UITableView
,
2 ответа
Лучший способ проверить это - написать небольшие тесты. Я не знаю, сколько объектов вы имеете дело, но если это меньше, чем несколько сотен, то вы, вероятно, не заметите большой разницы между containsObject:
, indexOfObjectPassingText:
или даже просто перебирать все объекты вручную.
Это звучит как NSMutableDictionary
больше подходит для вашего случая использования на самом деле. Почему вы не храните свои объекты в словаре, который индексируется идентификатором вашего объекта? Тогда вы сможете действительно быстро найти их по идентификатору, а также можете легко перебирать их, если это необходимо.
Вы можете переопределить -isEqual:
а также -hash
в твоем классе. Если вы это сделаете, он будет работать с NSOrderedSet
быстрый поиск. Это может быть так просто, как:
- (BOOL)isEqual:(id)otherObject
{
return self.myID == otherObject.myID;
}
- (NSUInteger)hash
{
return self.myID;
}
Вот полный пример:
#import <XCTest/XCTest.h>
@interface MyClass : NSObject
@property (nonatomic) NSInteger myID;
@property (nonatomic, strong) NSDate *date;
@end
@implementation MyClass
- (BOOL)isEqual:(MyClass*)otherObject
{
return self.myID == otherObject.myID;
}
- (NSUInteger)hash
{
return self.myID;
}
@end
@interface MyTests : XCTestCase
@end
@implementation MyTests
- (void)testExample
{
MyClass *obj1 = [[MyClass alloc] init];
obj1.myID = 1;
obj1.date = [NSDate dateWithTimeIntervalSince1970:20000];
MyClass *obj2 = [[MyClass alloc] init];
obj2.myID = 2;
obj2.date = [NSDate dateWithTimeIntervalSince1970:10000];
MyClass *obj3 = [[MyClass alloc] init];
obj3.myID = 1;
obj3.date = [NSDate dateWithTimeIntervalSince1970:30000];
MyClass *obj4 = [[MyClass alloc] init];
obj4.myID = 3;
obj4.date = [NSDate dateWithTimeIntervalSince1970:30000];
NSOrderedSet *set = [[NSOrderedSet alloc] initWithArray:@[obj1, obj2]];
XCTAssertEqualObjects(((MyClass *)[set firstObject]).date, obj1.date);
XCTAssertEqualObjects(((MyClass *)[set lastObject]).date, obj2.date);
XCTAssertTrue([set containsObject:obj1]);
XCTAssertTrue([set containsObject:obj3]);
XCTAssertFalse([set containsObject:obj4]);
}
@end