Ассоциативный массив против SplObjectStorage
Я работаю над кодом для управления коллекцией уникальных объектов. Первый прототип этого кода использует ассоциативный массив, в основном так, как я всегда это делал.
Тем не менее, я также заинтересован в использовании функциональных возможностей, которые были добавлены в более современные версии PHP, такие как SplObjectStorage, для этого, частично, как опыт обучения, отчасти потому, что он должен предлагать преимущества (тесты, которые я имею что SplObjectStorage может быть быстрее, чем массивы во многих случаях).
Текущая реализация имеет ассоциативный массив, который я проверяю с помощью in_array, чтобы увидеть, находится ли объект уже в массиве, перед добавлением к нему нового объекта.
Большая проблема, которую я вижу с помощью SplObjectStorage, заключается в том, что на первый взгляд не кажется, что поддерживает поведение ассоциативного массива key/value и может рассматриваться только как индексированный массив. Однако документация для новых функций PHP не соответствует стандартам документации более установленных частей языка, и я могу просто что-то упустить.
Можно ли использовать SplObjectStorage вместо ассоциативного массива? Если да, как определить ключ при добавлении нового объекта? Что еще более важно, каковы относительные преимущества и недостатки SplObjectStorage по сравнению с ассоциативными массивами?
Ответы
Ответ 1
Вы не должны видеть SplObjectStorage
как хранилище ключей, а просто набор объектов. Что-то в комплекте или нет, но его позиция не важна.
"ключ" элемента в SplObjectStorage
на самом деле является хешем объекта. Это делает невозможным добавление нескольких экземпляров одного и того же экземпляра объекта в SplObjectStorage
, поэтому вам не нужно проверять, существует ли копия перед добавлением.
Однако в PHP 5.4
есть новый метод под названием getHash()
, который вы можете переопределить, который вернет "хэш" объекта. Это - в некотором смысле - возвращает/устанавливает ключ, чтобы вы могли его хранить в разных условиях.
Основным преимуществом SplObjectStorage
является то, что вы получаете множество методов для работы и взаимодействия с разными наборами (contains()
, removeAll()
, removeAllExcept()
и т.д.). Его скорость немного лучше, но использование памяти хуже, чем обычные массивы PHP.
Ответ 2
Результаты после запуска теста с 10000 итерациями на PHP 5.6.13
:
+------------------+----------------+----------------+---------+
| Type | Time to fill | Time to check | Memory |
+------------------+----------------+----------------+---------+
| SplObjectStorage | 0.021285057068 | 0.019490000000 | 2131984 |
| Array | 0.021125078201 | 0.020912000000 | 1411440 |
+------------------+----------------+----------------+---------+
Как видите, Array
не заметно быстрее, чем SplObjectStorage
, но использует на 34% меньше памяти.
Ответ 3
Когда вся память, выделенная для массива, будет исчерпана, выделенная ему память будет удвоена. В этом контексте коллекция объектов может быть более эффективной структурой.