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
Другие вопросы по тегам