Наборы: неупорядоченные наборы объектов
Набор является неупорядоченным набором объектов, как показано на рисунке 1. Можно использовать наборы в качестве альтернативы массивам, когда порядок элементов не важен и производительность тестирования, является ли объект в наборе, важно. Даже при том, что массивы упорядочиваются, тестирование их для членства медленнее, чем тестирование наборов.
Основные принципы набора
NSSet
объект управляет неизменным набором отдельных объектов — т.е. после создания набора Вы не можете добавить, удалить или заменить объекты. Можно, однако, изменить сами отдельные объекты (если они поддерживают модификацию). Переменчивость набора не влияет на переменчивость объектов в наборе. Если набор редко изменяется или изменяет оптовую торговлю, необходимо использовать неизменный набор.
NSMutableSet
, подкласс NSSet
, непостоянный набор отдельных объектов, позволяющий дополнение и удаление записей в любое время, автоматически выделяя память по мере необходимости. Необходимо использовать непостоянный набор, если набор изменяется инкрементно или является очень большим — поскольку большое количество занимает больше времени для инициализации.
NSCountedSet
, подкласс NSMutableSet
, непостоянный набор, к которому можно добавить определенный объект несколько раз; другими словами, элементы набора не обязательно отличны. Считаемый набор также известен как сумка. Набор сохраняет счетчик связанным с каждым отдельным объектом вставленный. NSCountedSet
объекты отслеживают объекты числа раз, вставляются и требуют, чтобы объекты были удалены то же число раз для завершенного удаления объекта из набора. Таким образом, даже если объект был добавлен многократно, существует только один экземпляр объекта в считаемом наборе. countForObject:
метод возвращает число раз, указанный объект был добавлен к этому набору.
Объекты в наборе должны ответить на NSObject
методы протокола hash
и isEqual:
(см. NSObject
для получения дополнительной информации). Если непостоянные объекты хранятся в наборе, любой hash
метод объектов не должен зависеть от внутреннего состояния непостоянных объектов, или непостоянные объекты не должны быть изменены, в то время как они находятся в наборе. Например, непостоянный словарь может быть помещен в набор, но Вы не должны изменять его, в то время как это находится в там. (Обратите внимание на то, что может быть трудно знать, является ли данный объект в наборе).
NSSet
обеспечивает много методов инициализатора, такой как setWithObjects:
и initWithArray:
, тот возврат NSSet
объект, содержащий элементы (если таковые имеются), Вы передаете в как параметры. Объекты, добавленные к набору, не копируются (если Вы не передаете YES
как параметр initWithSet:copyItems:
). Скорее сильная ссылка к объекту добавляется к набору. Для получения дополнительной информации о копировании и управлении памятью, посмотрите Копирование Наборов.
Наборы, исключая NSCountedSet
, предпочтительные наборы, если Вы хотите быть уверенными, что никакой объект не представлен несколько раз, и нет никакого результирующего эффекта для добавления объекта несколько раз.
Непостоянные наборы
Можно создать NSMutableSet
объект с помощью любого из инициализаторов, предоставленных NSSet
. Можно создать NSMutableSet
объект от экземпляра NSSet
(или наоборот) использование setWithSet:
или initWithSet:
.
NSMutableSet
класс обеспечивает методы для добавления объектов к набору:
addObject:
добавляет отдельный объект к набору.addObjectsFromArray:
добавляют все объекты от указанного массива до набора.unionSet:
добавляют все уже не присутствующие объекты от другого набора.
NSMutableSet
класс дополнительно обеспечивает эти методы для удаления объектов из набора:
intersectSet:
удаляет все объекты, которые не находятся в другом наборе.removeAllObjects
удаляет все объекты из набора.removeObject:
удаляет определенный объект из набора.minusSet:
удаляет все объекты, которые находятся в другом наборе.
Поскольку NSCountedSet
подкласс NSMutableSet
, это наследовало все эти методы. Однако некоторые из них ведут себя немного по-другому с NSCountedSet
. Например:
unionSet:
добавляют все объекты от другого набора, даже если они уже присутствуют.intersectSet:
удаляет все объекты, которые не находятся в другом наборе. Если существуют многократные экземпляры того же объекта в любом наборе, получающийся набор содержит тот объект так же много раз как набор с меньшим количеством экземпляров.minusSet:
удаляет все объекты, которые находятся в другом наборе. Если объект присутствует несколько раз в считаемом наборе, он только удаляет один экземпляр его.
Используя наборы
NSSet
класс обеспечивает методы для запросов элементов набора:
allObjects
возвращает массив, содержащий объекты в наборе.anyObject
возвраты некоторый объект в наборе. (Объект выбран в удобстве не наугад.)count
возвращает число объектов в настоящее время в наборе.member:
возвращает объект в наборе, который равен указанному объекту.intersectsSet:
тесты, совместно используют ли два набора по крайней мере один объект.isEqualToSet:
тесты, равны ли два набора.isSubsetOfSet:
тесты, присутствуют ли все объекты, содержавшиеся в наборе также, в другом наборе.
NSSet
метод objectEnumerator
позволяет Вам пересечь элементы набора один за другим. ИmakeObjectsPerformSelector:
и makeObjectsPerformSelector:withObject:
методы предусматривают отправку сообщений на отдельные объекты в наборе. В большинстве случаев быстрое перечисление должно использоваться, потому что это быстрее и более гибко, чем использование NSEnumerator
или makeObjectsPerformSelector:
метод. Для больше на перечислении, посмотрите Перечисление: Пересечение Элементов Набора.
Хэш-таблицы
NSHashTable
класс сконфигурирован по умолчанию для содержания объектов во многом как NSMutableSet
делает. Это также позволяет дополнительные возможности хранения, которые можно адаптировать для конкретных случаев, такой как тогда, когда Вам нужны усовершенствованные опции управления памятью, или когда Вы хотите содержать определенный тип указателя. Например, таблица карты на рисунке 2 сконфигурирована для содержания слабых ссылок на ее элементы. Можно также указать, хотите ли Вы скопировать объекты, ввел в набор.
Можно использовать NSHashTable
возразите, когда Вы хотите неупорядоченный набор элементов, использующий слабые ссылки. Например, предположите, что у Вас есть глобальная хэш-таблица, содержащая некоторые объекты. Поскольку глобальные объекты никогда не собираются, ни одно из его содержания не может быть освобождено, если они не сохранены слабо. Хэш-таблицам, сконфигурированным для содержания объектов слабо, не принадлежит их содержание. Если нет никаких сильных ссылок к объектам в такой хэш-таблице, те объекты освобождены. Например, хэш-таблица на рисунке 2 содержит слабые ссылки на свое содержание. Объекты A, C, и Z будут освобождены, но остается остальная часть объектов.
Для создания хэш-таблицы инициализируйте его с помощью initWithOptions:capacity:
метод и надлежащие опции функций указателя. Также можно инициализировать его использование initWithPointerFunctions:capacity:
и надлежащие экземпляры NSPointerFunctions
. Для получения дополнительной информации о различных опциях функций указателя посмотрите Опции Функции Указателя.
NSHashTable
класс также определяет hashTableWithWeakObjects
конструктор удобства для создания хэш-таблицы со слабыми ссылками на ее содержание. Если Вы храните объекты, это должно только использоваться.
Для конфигурирования хэш-таблицы для использования произвольных указателей инициализируйте его с обоими NSPointerFunctionsOpaqueMemory
и NSPointerFunctionsOpaquePersonality
опции. При использовании хэш-таблицы для содержания произвольных указателей C функционируют API для void *
указатели должны использоваться. Для получения дополнительной информации см. Хэш-таблицы. Например, можно добавить указатель на int
значение с помощью подхода, показанного в Перечислении 1.
Хэш-таблица перечисления 1 сконфигурирована для необъектных указателей
NSHashTable *hashTable=[[NSHashTable alloc] initWithOptions: |
NSPointerFunctionsOpaqueMemory |NSPointerFunctionsOpaquePersonality |
capacity: 1]; |
NSHashInsert(hashTable, someIntPtr); |
Когда сконфигурировано для использования произвольных указателей хэш-таблице связали риски с использованием указателей. Например, если указатели относятся к стековым данным, создаваемым в функции, те указатели не допустимы за пределами функции, даже если хэш-таблица. Попытка получить доступ к ним приведет к неопределенному поведению.