2015-08-08 6 views
0

Я пытался понять это на некоторое время, и я не совсем понимаю, почему и как это работает.Почему NSArray из NSStrings работает как ключ для NSMutableDictionary?

Мне нужно сохранить пару идентификаторов (отдельно, поэтому они не могут быть объединены вместе), которые сопоставляются с объектом. Первоначально я использовал экземпляр NSMutableDictionary верхнего уровня для этого, в нем лежали вложенные объекты NSMutableDictionary. Для того, чтобы получить значение пары идентификаторов, я мог бы назвать:

[[myTopLevelDictionary objectForKey:key1] objectForKey:key2] 

И это будет работать надлежащим образом хорошо, даже несмотря на отслеживании вложенных NSMutableDictionary экземпляров требует немного дополнительной работы.

Вчера мне было интересно, можно ли использовать пару объектов NSString в качестве ключа напрямую. Поэтому я попытался создать экземпляр NSArray с двумя объектами NSString и использовать это в качестве ключа вместо этого, и она работала:

NSMutableDictionary *dict = [NSMutableDictionary dictionary]; 
NSArray *key = [NSArray arrayWithObjects:@"A", @"B", nil]; 

[dict setObject:@"foobar" forKey:key]; 

NSLog(@"%@", [dict objectForKey:key]); 
NSLog(@"%@", [NSArray arrayWithObjects:@"A", @"B", nil]; 

// Even this seems to work? 
NSMutableArray *key2 = [NSMutableArray arrayWithObjects:@"A", @"B", @"C", nil]; 
[key2 removeLastObject]; 

NSLog(@"%@", key2); 

Все три случая успешно напечатать «Foobar». Если я изменил порядок объектов NSString в массиве, тогда словарь вернет нуль вместо этого. Если я добавлю или удалю объекты NSString, опять же, словарь правильно вернет нуль. Кажется, что только объект NSArray с правильными объектами NSString, содержащими правильное содержимое в правильном порядке, получает соответствующее значение.

Мой вопрос ... Почему это работает, и как?

Я знаю, что хеширование имеет какое-то отношение к нему, но передача хэша объекту NSArray просто возвращает объект, поэтому я не могу себе представить, что это имеет к нему какое-то отношение. Тогда я подумал, что NSDictionary пытался получить описание NSArray и использовать это как строковый ключ, но я не уверен, как проверить эту теорию, поскольку хэш NSString не совпадает с хэш-файлом NSArray (поэтому я не могу просто используйте ключ NSString, который реплицирует вывод [[NSArray arrayWithObjects:@"A", @"B", nil] description]).

Не поймите меня неправильно, было бы здорово, если бы я мог использовать NSArray/NSString/NSMutableDictionary, как это, я просто хочу убедиться, что все работает так, как я думаю, и что это не так. какое-то странное неопределенное поведение или что-то в этом роде.

+1

'NSArray' реализует глубокое равенство: он отправляет' isEqual: 'каждому из элементов, сравнивая их с элементами другого массива. Если каждый элемент из 'self' равен элементу в соответствующей позиции во втором массиве, он возвращает' YES', else (или если подсчеты двух массивов не совпадают), он возвращает 'NO'. Хеширование согласуется с этим поведением (равные массивы обязательно равны хэшам), а также 'NSArray' является гибким, поэтому нет причин, по которым массив строк не будет работать как ключ. –

+0

Лично я бы не стал полагаться на него, особенно если каждый из ваших ключей будет иметь одинаковое значение хэша (количество массивов). Это потенциально даст вам сильно неуравновешенный набор ведер. –

ответ

1

Независимо от того, какой ключ вы используете для ввода ключа/значения в словаре, будет хэшироваться и использоваться как реальный ключ внутри. Вы должны быть очень осторожны при использовании Array в качестве ключа, потому что вы производите его, его хэш изменится, и поэтому вы больше не сможете получить доступ к этому значению.

Чтобы ответить на ваш вопрос, он работает, потому что ключ (NSArray) может быть хэширован. Как это работает: поскольку хранимый «ключ» является хэшем NSArray, а не самим массивом (для целей производительности и размера хранилища). Когда вы используете NSString в качестве ключа, он делает то же самое и сохраняет хэш строки внутри.