Что лучше, NSSet содержитобъект или быстрый enum?
-
27-10-2019 - |
Вопрос
Мне нужно определить, включен ли объект в основные данные о отношениях (что является NSSet), и я пытаюсь решить, какое из двух решений лучше:
Решение 1)
if ([managedObject.items containsObject:itemOfInterest])
return …
Решение 2)
for (NSManagedObject *item in managedObject.items)
if ([item == itemOfInterest])
return …
Решение 1 более краткое, но ref ref Class NSSet говорит, что быстрое перечисление работает лучше, чем объект -энтузиатор NSSet. Он также работает лучше, чем содержит?
Решение
Я всегда ходил на вариант 1.
Это более кратко, я могу точно сказать, что вы пытаетесь сделать с кодом, и есть вероятность, что содержит, содержит довольно изящные оптимизации.
Другие советы
Ни один. Вы должны использовать NSFetchRequest
с предикатом. Ваши шаблоны могут случайно обвинить все отношения, что очень дорого и не требуется, чтобы проверить, содержит ли он один объект. Есть способы быть осторожными и не винить все отношения, но это хрупкие (небольшие изменения в вашем поиске приводят к огромным изменениям в производительности), и поэтому лучше иметь привычку использовать NSFetchRequest
а не коллекция для поиска. Я люблю устанавливать свой fetchLimit
1 в этих случаях, так что, как только он его найдет, он перестает искать.
Для удобства вы можете создать -containsFoo:
Метод на вашем управляемом объекте, чтобы вам не приходилось писать логику извлечения повсюду.
Ваши два решения выше тонко отличаются. Первый проверяет, есть ли объект в коллекции, который isEqual:
к itemOfInterest
. Анкет Ваше второе решение проверяет, есть ли объект в коллекции в том же месте памяти, что и itemOfInterest
. Анкет Для объектов с пользовательскими isEqual:
Логика, они могут вернуть разные результаты. Это означает, что решение 2 может быть немного быстрее для неточных коллекций данных, но это потому, что вы на самом деле тестируете другое дело, а не из-за перечисления объектов. (В действительности это верно только для небольших коллекций; см. Ниже.)
Почему вы считаете, что решение 1 использует -objectEnumerator
?
Как указывает @James Raybould, вы, как правило, не должны пытаться переписать встроенные методы по соображениям производительности. Если isEqual:
Версия решения 2 была быстрее, чем решение 1, разве вы не думаете, что Apple внедрила бы -containsObject:
Используя код в решении 2?
На самом деле, основной CFSet
реализуется как хэш, поэтому проверка на содержание является логарифмической, а не линейной. Вообще говоря, для больших наборов с разумными хэш -функциями решение 1 будет быстрее. Смотрите код для него в Cfset.c. Анкет Ищу CFSetContainsValue()
. Анкет Конечно, реализация CFSET не гарантированно остается прежней, но она полезна для понимания того, как проблемы производительности обычно решаются в какао.