Что такое коллекция в php
Что такое коллекция объектов в php
Собственно есть задача, создать объект со вложенной коллекций объектов tickets. Но что это такое?
Вот есть объект со вложенным объектом tickets:
tickets нужно представить в виде коллекции объектов. А как он должен выглядеть и, соответственно, создаваться?
2 ответа 2
Collection Данный интерфейс предназначен для описания базовых функций работы с множеством объектов. Он наследует интерфейсы Countable и Iterable, что позволяет получать количество объектов в коллекции и выполнять обход и применение пользовательской функции для каждого объекта коллекции. Интерфейс коллекции подразумевает, что в коллекции находятся объекты одного типа.
В вашем случае больше всего подойдёт реализация коллекции наборы.
Реализации наборов Наборы представлены единственной реализацией UniqueStore. Объекты в хранилище UniqueStore. Уникальность объектов обеспечивается за счет метода getIdentity(), который возвращает идентификаторы объектов. В хранилище UniqueStore не могут присутствовать несколько объектов с одинаковыми идентификаторами. Внутренняя структура хранилища уникальных объектов UniqueStore построена на основе ассоциативных связей между объектами и их идентификаторами. Это дает возможность реализовывать все операции хранилища с помощью ассоциативных выборок, что очень сильно повышает скорость его работы. Сложность работы алгоритмов хранилища уникальных объектов равна O(1), что означает, что время установки/получения объектов не изменяется в зависимости от размера хранилища. Хранилище уникальных объектов UniqueStore поддерживает любые типы данных для значений.
I Portal
IT новости | теория | практика
Коллекции в PHP: особенности, пример на практике
Цель класса Collection
Приложения часто имеют объекты, которые содержат группу других объектов. Класса Collection обеспечивает объектно-ориентированную оболочку вокруг массива, и реализует механизм, который позволяет ленивую загрузку. Ленивая загрузка откладывает создание элементов коллекции, пока они на самом деле не нужны. Это явление называется «ленивая загрузка», потому что объект самостоятельно определяет, когда ему реализовывать объекты своих компонентов, чем создавать их, когда они реализованы.
Функциональные требования класса Collection следующие:
В базовом виде класс Collection выглядит следующим образом:
Наследуемые классы Collection могут переопределять метод addItem() с помощью подсказки типа, которая гарантирует, что добавляемые элементы имеют правильный тип для желаемой коллекции. Вот пример:
Используя эту технику, с помощью малого количества кода, вы можете создавать классы наследники, которые обеспечивают соблюдение типа данных для элементов коллекции.
Методы removeItem() и getItem() принимают ключ в качестве параметра, который указывает, какие элементы будут удалены или извлечены. Исключение следует выдать, если указан неверный ключ:
Возможно, вы захотите узнать, сколько предметов в коллекции. Функция sizeof возвращает количество элементов в массиве, так что вы будете использовать её для реализации вашего метода length():
public function length() < return sizeof($this->_members); >
Поскольку getItem() выдает исключение, если передан неверный ключ, вам необходимо иметь средство определение, существует ли данный ключ в коллекции. Метод exists() позволяет это проверить перед вызовом getItem():
Этот подход позволяет вам использовать блок try … catch для отлова недопустимых ключей или вызвать Метод exists() перед вызовом getItem(), в зависимости от того, какой метод более удобен.
Теперь, когда мы добавили все основные методы в класс, можно рассмотреть, как класс Collection используется.
Использование класса Collection:
Этот пример может быть еще не особенно полезен, но он должен дать вам некоторое представление о том, как используется класс Collection.
Добавить комментарий Отменить ответ
Для отправки комментария вам необходимо авторизоваться.
Коллекции объектов в PHP
На протяжении последних 5 лет я работаю с PHP. У него есть достаточно разных проблем, но это никогда не мешало создавать отлично работающие продукты.
Не смотря на это, есть ряд вещей, которые выполняются внутри достаточно «криво». Один из вопросов, который постоянно тратил мои нервы, был вопрос работы с множествами объектов с помощью массивом данных.
На мой взгляд, массивы в PHP имеют достаточно широкую функциональность, что, кстати, является одной из проблем при работе с множествами объектов.
В результате было принято решение о создании пакета, который должен работать с множествами однотипных объектов (коллекциями).
И так, представляю вашему вниманию пакет Rmk\Collection.
Интерфейсы
Интерфейсы коллекций предназначены для описания функциональности и классификации типов коллекций.
Базовым интерфейсом коллекций является интерфейс Collection.
Интерфейсы Map, Set, List, Queue и Deque наследуют интерфейс Collection и добавляют собственную функциональность.
Интерфейс Iterable предназначен для обхода объектов коллекции. Он поддерживается всеми интерфейсами коллекций.
Iterable
Данный интерфейс предоставляет возможность выполнять обход объектов коллекции и применять к каждому объекту пользовательскую функцию.
Collection
Данный интерфейс предназначен для описания базовых функций работы с множеством объектов. Он наследует интерфейсы Countable и Iterable, что позволяет получать количество объектов в коллекции и выполнять обход и применение пользовательской функции для каждого объекта коллекции. Интерфейс коллекции подразумевает, что в коллекции находятся объекты одного типа.
Map
Данный интерфейс предназначен для описания функциональности карты объектов. Карта объектов предназначена для построения ассоциативных связей между объектами, где один из объектов является ключем, а другой значением. Интерфейс карты объектов подразумевает, что в карте находятся ключи одного типа. Интерфейс карты объектов подразумевает, что в карте находятся значения одного типа. Интерфейс карты объектов наследует интерфейс Collection.
Set
Данный интерфейс предназначен для описания функциональности набора объектов, где объекты являются уникальными в рамках коллекции. Уникальность объектов осуществляется с помощью метода getIdentity(). Интерфейс набора объектов наследует интерфейс Collection.
Queue
Данный интерфейс предназначен для описания функциональности очереди объектов. Очередь объектов предназначена для описания структуры данных, когда объекты добавляются в конец очереди, а забираются с начала очереди. Интерфейс очереди объектов наследует интерфейс Collection.
Deque
Данный интерфейс предназначен для описания функциональности двунаправленной очереди объектов. Интерфейс двунаправленной очереди объектов наследует интерфейс очереди объектов Queue и добавляет дополнительную функциональность. Функциональность двунаправленной очереди объектов подразумевает работу с очередью с обеих сторон.
SequentialList
Данный интерфейс предназначен для описания функциональности списка объектов. Списком объектов является последовательность объектов, где объекты хранятся под последовательными целочисленными индексами. Кроме общей функциональности списка объектов, данный интерфейс определяет метод reverseEach() аналогичный методу Iterable::each() за исключением того, что метод reverseEach() обходит список в обратном порядке. Интерфейс списка объектов наследует интерфейс Collection.
Реализации карт
Карты представлены реализациями HashMap и HashStore.
Часть функциональности HashMap и HashStore наследуется от абстрактных классов AbstractCollection и AbstractMap.
Внутренняя структура карт HashMap и HashStore построена на основе сети ассоциативных связей. Это дает возможность реализовывать все операции карт с помощью ассоциативных выборок, что очень сильно повышает скорость их работы. Сложность работы алгоритмов карт равна O(1), что означает, что время установки/получения объектов не изменяется в зависимости от размера карт.
Карты HashMap и HashStore поддерживают любые типы данных для ключей и значений. Это является функциональным преимуществом по сравнению с стандартными Php массивами.
Ключи карты HashMap являются уникальными. Значения карты HashMap не являются уникальными, что позволяет ассоциировать одно значение с несколькими ключами.
Ключи и значения карты HashStore являются уникальными, что позволяет организовывать хранилище уникальных ассоциированных объектов.
Карта HashStore работает в среднем на 20% быстрее карты HashMap. Данное преимущество получено за счет уникальности объектов в HashStore, что требует меньшего количества ассоциативных связей.
Реализации наборов
Наборы представлены единственной реализацией UniqueStore.
Объекты в хранилище UniqueStore. Уникальность объектов обеспечивается за счет метода getIdentity(), который возвращает идентификаторы объектов. В хранилище UniqueStore не могут присутствовать несколько объектов с одинаковыми идентификаторами.
Внутренняя структура хранилища уникальных объектов UniqueStore построена на основе ассоциативных связей между объектами и их идентификаторами. Это дает возможность реализовывать все операции хранилища с помощью ассоциативных выборок, что очень сильно повышает скорость его работы. Сложность работы алгоритмов хранилища уникальных объектов равна O(1), что означает, что время установки/получения объектов не изменяется в зависимости от размера хранилища.
Хранилище уникальных объектов UniqueStore поддерживает любые типы данных для значений.
Реализации списков
Списки представлены реализациями ArrayList и LinkedList.
Списки объектов ArrayList и LinkedList поддерживают последовательный порядок индексов при изменении своей структуры.
Производительность списков объектов ArrayList и LinkedList зависит от количества изменений их структуры. Исходя из этого, самыми «дешевыми» являются операции работы с концом списка (добавление / удаление), а самыми «дорогими» — операции работы с началом списка (добавление / удаление). Сложность работы алгоритмов списка объектов равна O(n * (count — index)), где n — операция; count — размер списка; index — индекс, по которому выполняется операция.
Списки объектов ArrayList и LinkedList поддерживают любые типы данных для значений.
Связанный список объектов LinkedList реализует интерфейс двунаправленной очереди объектов Deque и наследует функциональность от ArrayList.
Реализации очередей
Конкретные реализации очередей отсутствуют, так как связанный список LinkedList отлично покрывает их функциональность.
Несколько примеров использования
Примеры использования карт:
Примеры использования наборов:
Примеры использования списков:
Преимущества и недостатки
Коллекции — Ключевые аспекты веб-разработки на PHP
Вероятно, тема текущего урока — самая простая и самая базовая из всего, что описывалось и будет описываться в курсе. Но одновременно она наиболее «мозговзрывная».
Обработка коллекций — крайне частая операция в коде. Так или иначе, почти все, с чем мы имеем дело, представлено набором данных. Список пользователей, список страниц, список дат, список строк, список серверов и так далее. Львиная доля информации представлена в виде списков или появляется в результате обработки списков.
На текущий момент, вероятно, вам известен только один подход к их обработке — циклы. И хотя циклы действительно решают любую задачу, есть более удобные механизмы, позволяющие писать код, который проще читать и легче поддерживать. Например, в JavaScript канонический способ работы с коллекциями — функции высшего порядка. Посмотрите внимательно:
Возможность так писать доступна в js из коробки, но php — другое дело. Для эффективной работы вам придётся «обмазаться» дополнительными библиотеками, такими как эта. Тогда код на php для той же задачи станет таким:
Кода, конечно, значительно больше (таков уж php), и используются аж две новых библиотеки, но появляется высокая выразительность. Когда вы начнёте понимать соответствующий синтаксис, то полюбите подобные конструкции.
Коллекциям на Хекслете посвящено аж целых два с половиной курса (один из курсов готовит необходимую почву для них). Здесь тот самый случай, когда лучше значит больше. Обработка коллекций, во многом, — алгоритмическая история, и она просто так сама в голове не сформируется. Нужно время и задачки, чтобы появились необходимые связи в мозгу. И даже этого времени не хватит. Во всех оставшихся курсах так или иначе будут появляться коллекции, и вы сможете отточить свои навыки по работе с ними. А так как эта тема базовая и мало зависит от других аспектов, мы начнём затрагивать её в самом начале, буквально со следующих курсов.
Важно, что кроме самих коллекций, навыки решения даже простейших алгоритмов хорошо развивают и структурируют рассудочное мышление. То есть эти курсы преследуют две цели:
Остались вопросы? Задайте их в разделе «Обсуждение»
Вам ответят команда поддержки Хекслета или другие студенты.
Коллекции объектов в PHP. Часть вторая
Прошло почти 3 недели с момента публикации моего первого поста о коллекциях объектов в PHP. За это время было сделано много работы и получено много опыта, которым я хочу поделиться. Наибольшее количество изменений претерпели карты, большая часть внимания будет уделена именно им.
Что было сделано?
Кроме вышеуказанного списка были еще кандидаты, которые не вошли в план текущего релиза:
Интерфейсы коллекций
Разработанные ранее интерфейсы коллекций отреагировали достаточно стабильно на новый план развития. Диаграмма интерфейсов текущей версии выглядит так:
Как видно из диаграммы все интерфейсы коллекций наследуют интерфейс IteratorAggregate, что дает возможность выполнять обход коллекций с помощью foreach(). Проблема с warning, который выскакивает при обработке карт с помощью foreach() все еще осталась, но по скольку такие ситуации действительно бывают редко, я решил закрыть на это глаза.
Реализации карт
Карты представлены реализациями HashMap, HashSet и HashTable. Каждая из данных реализаций имеет собственные специализации для упрощенного использования.
HashTable
Внутренняя структура карты HashTable построена на основе единственного PHP массива. Это дает возможность быстрой работы по ключу O(1), но плохо влияет на возможность работы по значению, которая выполняется обычным перебором O(n).
Ключи карты HashTable являются уникальными. Значения карты HashTable не являются уникальными, что позволяет ассоциировать одно значение с несколькими ключами.
Карта HashTable поддерживает строки и целые числа для ключей и строки, целые числа и объекты для значений.
Хеширование ключей и значений не выполняется. Методы getKeyHash() и getValueHash() выбрасывают исключение.
HashMap & HashSet
Внутренняя структура карт HashMap и HashSet построена на основе сети ассоциативных связей. Это дает возможность реализовывать все операции карт с помощью ассоциативных выборок. Сложность работы алгоритмов карт равна O(1), что означает, что время установки/получения объектов не изменяется в зависимости от размера карт.
Ключи карты HashMap являются уникальными. Значения карты HashMap не являются уникальными, что позволяет ассоциировать одно значение с несколькими ключами.
Ключи и значения карты HashSet являются уникальными, что позволяет организовывать хранилище уникальных ассоциаций.
Карты HashMap и HashSet поддерживают строки, целые числа и объекты для ключей и значений.
Реализации наборов, списков и очередей
Реализация наборов претерпела некоторые косметические изменения и обросла специализациями для упрощенного использования.
Диаграмма классов наборов.
Реализации списков и очередей остались практически без изменений.
Диаграмма классов списков и очередей.
Тестирование функциональности
Тестирование производительности
Наиболее интересным для меня было то, на сколько производительны полученные коллекции. Реализации наборов и последовательных списков я отбросил в сторону и сосредоточился на тестировании карт.
Платформу тестирования детально описывать не буду, так как не вижу в этом особого смысла. Дело в том, что данные тесты не предназначены для определения количественных характеристик, а скорее для демонстрации соотношений. Соотношения результатов тестов практически не менялись ни на разном железе, ни на разных операционных системах.
Результаты тестов в этом посте я снимал со своего ноутбука на Windows Vista 32 bit.
Тестирование времени установки пары ключ / значение
Тестирование времени выборки значения по ключу
Тестирование времени выборки ключа по значению
Тестирование объема потребляемой оперативной памяти
Некоторые интересные факты
В процессе работы всплыли некоторые интересные факты, которыми хочется поделиться.
Непостоянство spl_object_hash()
Думаю, многим знакома функция spl_object_hash().
Оказывается у нее есть одна, на мой взгляд, не очень хорошая особенность — непостоянство хешей.
Тест непостоянства spl_object_hast():
Внутреннее хеширование ключей массивов
В комментариях к моему прошлому посту пользователь Athari оставил ценный комментарий, часть которого я процитирую:
Зачем для строк вычислять md5? Похапэшные массивы — и так хэштаблицы, не нужно вычислять хэши на двух уровнях. Только память и вычислительные ресурсы впустую расходуются.
на 70% по сравнению со своим md5 хешированным аналогом. При этом время установки и доступа остается соизмеримым, но, конечно, в пользу «чистого» ключа.
Хеширование массивов
Вызов serialize забавен. Понимаю, «нужно» все типы поддерживать, но не такой же ценой.
Для воссоздания контекста напомню, что речь шла о том, что нужно было поддерживать массив как тип данных ключей коллекции. Для этого выполнялась его сериализация для приведения к строке, а после хеширование этой строки с помощью md5().
Действительно «дорогая» цена. В текущей реализации я вообще отказался от поддержки массивов в качестве ключей карты.
Особенно хочется остановить на пункте «Небезопасно.» Дело в отсутствие обратной связи между данными и хешем (как бы «дорого» мы его не получили). Если клиентский код сохранит ссылку на массив, который мы захешировали, и изменит его, то хеш устареет. Получить информацию о том, что это тот же массив возможности уже не будет. Тоже самое относится и к другим скалярным типам данных.
Есть ли выход? Единственное, что приходит на ум, это использовать массив через объект обертку (ArrayObject, etc. ). В таком случае можно хотя бы получить «непостоянный» spl_object_hash().
Заключение
Пожалуй, самый главный вопрос, на который нужно дать ответ: «Готовы ли Вы заплатить такую цену по производительности за это решение?». Я уверен, что никто не готов. И я в том числе. Когда я создал графики результатов тестирования производительности, я был удивлен. Я ожидал гораздо меньших соотношений по сравнению со стандартными реализациями, хотя прекрасно понимал, что данное решение явно проигрывает в этом аспекте. Я сперва даже пытался найти решение проблем, но, увы, ничего не вышло. Основная проблема заключается в том, что даже вызов метода является «дорогой» операцией в этом случае. Что касается объема потребляемой оперативной памяти, то до сих пор не пойму, на что расходуется столько ресурсов. Единственное полезное новшество — это двустороннее хеширование карты, что дает возможность выбирать из нее по значению в рамках O(1).
В целом, считаю, что данный проект потерпел фиаско, и причиной этому является аспект производительности.
Развитие
Исходя из моей аналитики подобное решение все же появится со временем. Лучшее место для него — пакет SPL. Может быть это будет и не SPL, а какой-то другой PECL модуль, который со временем войдет в стандартную сборку PHP. В любом случае что-то удовлетворительное или хорошее получится только при грамотной реализации на С. Кстати, если кто-то заинтересовался данным проектом и хочет помочь реализовать его в качестве PECL модуля, буду рад сотрудничеству.
Что делать дальше?
Возможно, просто довольствоваться тем, что имеем на текущий момент и ждать. Ведь даже сейчас все достаточно неплохо.
Лично я решил создать более легковесные реализации, которые просто будут немного помогать в повседневной жизни и не будут чем-то большим, чем есть стандартные PHP массивы. Уже сейчас есть некоторые наброски:
Если это кому-то интересно, пишите, я расскажу о идее более детально.
Исходные коды
Благодарности
Благодарю всех за конструктивные комментарии к прошлому посту. Они были очень полезны. Рад буду услышать Ваше мнение еще раз.
Спасибо, что дочитали до конца и извините за обилие графики, я старался размещать ее только там, где необходимо.