それにもかかわらず、非常に「曲がりくねった」内部で実行される多くのことがあります。 常に私の神経を浪費していた質問の1つは、一連のデータを使用してオブジェクトのセットを操作する問題でした。
私の意見では、PHPの配列にはかなり広い機能がありますが、これは、オブジェクトのセットを扱う際の問題の1つです。
何が好きではなかったのですか?
- 歴史的に開発された関数名とオブジェクト指向インターフェースの欠如 。
- キーがオブジェクトである連想配列を構築できない。
- 配列内のオブジェクトのタイプの独立した制御。
- リスト内のインデックスのシーケンスの独立した制御。
その結果、同じタイプ(コレクション)のオブジェクトのセットで動作するパッケージを作成することが決定されました。
そのため、Rmk \ Collectionパッケージを紹介します。
インターフェース
コレクションインターフェイスは、コレクションタイプの機能と分類を記述することを目的としています。
コレクションの基本インターフェイスは、コレクションインターフェイスです。
Map、Set、List、Queue、およびDequeインターフェイスは、Collectionインターフェイスを継承し、独自の機能を追加します。
Iterableインターフェイスは、コレクションオブジェクトをトラバースするように設計されています。 すべてのコレクションインターフェイスでサポートされています。
反復可能
このインターフェイスは、コレクションオブジェクトをトラバースし、各オブジェクトにカスタム関数を適用する機能を提供します。
収集
このインターフェイスは、多くのオブジェクトを操作する基本機能を説明するように設計されています。 CountableおよびIterableインターフェイスを継承します。これにより、コレクション内のオブジェクトの数を取得し、コレクション内の各オブジェクトにユーザー定義関数をクロールおよび適用できます。 コレクションインターフェイスは、コレクションに同じタイプのオブジェクトが含まれることを意味します。
地図
このインターフェイスは、オブジェクトのマップの機能を記述することを目的としています。 オブジェクトマップは、オブジェクトの関連付け関係を構築するように設計されています。オブジェクトの1つがキーで、もう1つが値です。 オブジェクトマップのインターフェイスは、マップに同じタイプのキーが含まれていることを意味します。 オブジェクトマップインターフェイスは、マップに同じタイプの値が含まれていることを前提としています。 オブジェクトマップインターフェイスは、コレクションインターフェイスを継承します。
セット
このインターフェイスは、オブジェクトがコレクション内で一意であるオブジェクトのセットの機能を記述することを目的としています。 オブジェクトの一意性は、getIdentity()メソッドを使用して実行されます。 オブジェクトセットインターフェイスは、コレクションインターフェイスを継承します。
キュー
このインターフェイスは、オブジェクトキューの機能を記述することを目的としています。 オブジェクトキューは、オブジェクトがキューの末尾に追加され、キューの先頭から取得される場合のデータ構造を記述することを目的としています。 オブジェクトキューインターフェイスは、コレクションインターフェイスを継承します。
デケ
このインターフェイスは、オブジェクトの双方向キューの機能を記述することを目的としています。 双方向オブジェクトキューインターフェイスは、キューオブジェクトキューインターフェイスを継承し、追加機能を追加します。 オブジェクトの双方向キューの機能は、両側でキューを操作することを意味します。
シーケンシャルリスト
このインターフェイスは、オブジェクトのリストの機能を記述することを目的としています。 オブジェクトのリストは、連続した整数インデックスの下にオブジェクトが格納されるオブジェクトのシーケンスです。 オブジェクトのリストの一般的な機能に加えて、このインターフェイスはIterable :: each()に似たreverseEach()メソッドを定義しますが、reverseEach()メソッドはリストを逆順にトラバースします。 オブジェクトリストインターフェイスは、コレクションインターフェイスを継承します。
カードの実装
マップは、HashMapおよびHashStoreの実装によって表されます。
HashMapおよびHashStoreの機能の一部は、AbstractCollectionおよびAbstractMap抽象クラスから継承されます。
HashMapおよびHashStoreマップの内部構造は、連想リンクのネットワークに基づいています。 これにより、連想サンプルを使用してすべてのカード操作を実装できるようになり、速度が大幅に向上します。 マップアルゴリズムの作業の複雑さはO(1)です。これは、オブジェクトのインストール/取得時間がカードのサイズに応じて変化しないことを意味します。
HashMapおよびHashStoreカードは、キーと値のあらゆるタイプのデータをサポートします。 これは、標準のPhpアレイよりも機能的に優れています。
HashMapカードのキーは一意です。 HashMapマップの値は一意ではないため、単一の値を複数のキーに関連付けることができます。
HashStoreマップのキーと値は一意であるため、一意の関連オブジェクトのストレージを整理できます。
HashStoreカードは、HashMapカードよりも平均20%高速で実行されます。 この利点は、HashStore内のオブジェクトの一意性により得られます。これにより、必要な結合リンクが少なくなります。
実装を設定する
キットは、UniqueStoreの独自の実装によって表されます。
UniqueStoreストレージ内のオブジェクト。 オブジェクトの一意性は、オブジェクトの識別子を返すgetIdentity()メソッドによって保証されます。 UniqueStoreリポジトリには、同じ識別子を持つ複数のオブジェクトを含めることはできません。
一意のオブジェクトのストアハウスの内部構造UniqueStoreは、オブジェクトとその識別子との関連性に基づいて構築されます。 これにより、連想サンプルを使用してすべてのストレージ操作を実装できるため、速度が大幅に向上します。 一意のオブジェクトを保存するためのアルゴリズムの操作の複雑さはO(1)です。これは、オブジェクトのインストール/取得時間がストレージのサイズに応じて変化しないことを意味します。
UniqueStoreは、値のすべてのタイプのデータをサポートします。
実装のリスト
リストは、ArrayListおよびLinkedListの実装によって表されます。
ArrayListおよびLinkedListオブジェクトリストは、構造が変更されたときにインデックスの順序を順番に維持します。
ArrayListおよびLinkedListオブジェクトリストのパフォーマンスは、それらの構造の変更の数に依存します。 これに基づいて、最も「安い」操作はリストの最後の操作(追加/削除)であり、最も「高価な」操作はリストの最初の操作(追加/削除)です。 オブジェクトリストアルゴリズムの操作の複雑さはO(n *(カウント-インデックス))です。ここで、nは操作です。 count-リストのサイズ。 index-操作が実行されるインデックス。
ArrayListおよびLinkedListオブジェクトリストは、値のデータ型をサポートします。
LinkedListオブジェクトのリンクリストは、Dequeオブジェクトの双方向キューを実装し、ArrayListから機能を継承します。
キューの実装
LinkedListリンクリストはその機能を完全にカバーしているため、特定のキューの実装はありません。
いくつかのユースケース
カードの使用例:
<?php namespace Rmk\Collection; use \UnexpectedValueException as UnexpectedValueException; use \InvalidArgumentException as InvalidArgumentException; use \stdClass as stdClass; include '../../bootstrap.php'; $map = new HashMap('stdClass', 'string'); $obj1 = new stdClass(); $obj2 = new stdClass(); $obj3 = new stdClass(); // / . $map->set('k1', $obj1); $map->set('k2', $obj2); $map->set('k3', $obj3); try { $map->set(27, $obj1); } catch (InvalidArgumentException $exc) { echo ' .'; } try { $map->set('k4', new UnexpectedValueException); } catch (InvalidArgumentException $exc) { echo ' .'; } // . $map->each(function($value, $key, $thisMap) { /** * @TODO: . */ } ); // . $map->remove($obj1); $map->remove($obj2); // . $map->removeKey('k3'); if ($map->isEmpty()) { /** * @TODO: , ? */ } // . $array = $map->toArray(); // ! , // . $objectMap = new HashMap('stdClass', 'stdClass'); try { $objectArray = $objectMap->toArray(); } catch (UnexpectedValueException $exc) { echo ' .'; }
セットの使用例:
<?php namespace Rmk\Collection; use \UnexpectedValueException as UnexpectedValueException; use \InvalidArgumentException as InvalidArgumentException; use \stdClass as stdClass; include '../../bootstrap.php'; $set = new UniqueStore('stdClass'); $obj1 = new stdClass(); $obj2 = new stdClass(); $obj3 = new stdClass(); // . $set->add($obj1); $set->add($obj2); $set->add($obj3); // . $set->add($obj3); try { $set->add(new UnexpectedValueException); } catch (InvalidArgumentException $exc) { echo ' .'; } // . $set->each(function($value, $thisSet) { /** * @TODO: . */ } ); // . $set->remove($obj1); $set->remove($obj2); $set->remove($obj3); // . $array = $set->toArray();
リストの使用例:
<?php namespace Rmk\Collection; use \UnexpectedValueException as UnexpectedValueException; use \InvalidArgumentException as InvalidArgumentException; use \OutOfRangeException as OutOfRangeException; use \stdClass as stdClass; include '../../bootstrap.php'; $list = new LinkedList('stdClass'); $obj1 = new stdClass(); $obj2 = new stdClass(); $obj3 = new stdClass(); // . $list->add(0, $obj1); $list->add(1, $obj2); $list->add(2, $obj3); try { $list->add(4, $obj1); } catch (OutOfRangeException $exc) { echo ' , .'; } // . $list->each(function($value, $index, $thisList) { /** * @TODO: . */ } ); // . $list->reverseEach(function($value, $index, $thisList) { /** * @TODO: . */ } ); // . $list->remove($obj1); $list->removeIndex(0); $list->removeFirst(); if ($list->isEmpty()) { echo ' .'; }
長所と短所
- +
- コレクション内のオブジェクトのタイプに対する信頼。
- 「配列関数」ではなくOOインターフェース(このパッケージを作成する主な理由)。
- SequentialList型のコレクション内のインデックスのシーケンスの信頼性。
- -
- 条件付きで低いパフォーマンス。 PHP実装から何を絞り出すことができるのか、絞り出そうとしました。 しかし、このパッケージがPECLモジュールとしてCで実装されていれば、ずっと速く動作します。
ソースコード
https://github.com/rmk135/Rmk-Framework