{"id":23219128,"url":"https://github.com/b2pweb/bdf-collections","last_synced_at":"2025-08-19T08:32:49.123Z","repository":{"id":36104114,"uuid":"220039864","full_name":"b2pweb/bdf-collections","owner":"b2pweb","description":"Implementation of commons collections, with java-like stream to apply transformations.","archived":false,"fork":false,"pushed_at":"2024-12-02T13:10:00.000Z","size":121,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-12-04T02:06:06.687Z","etag":null,"topics":["collections","functional","java-streams"],"latest_commit_sha":null,"homepage":null,"language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/b2pweb.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2019-11-06T16:20:24.000Z","updated_at":"2024-10-11T09:53:00.000Z","dependencies_parsed_at":"2024-02-26T14:58:40.728Z","dependency_job_id":null,"html_url":"https://github.com/b2pweb/bdf-collections","commit_stats":{"total_commits":47,"total_committers":2,"mean_commits":23.5,"dds":0.08510638297872342,"last_synced_commit":"3d84165b0a978b8a17d012f78f0e974398c673a8"},"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/b2pweb%2Fbdf-collections","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/b2pweb%2Fbdf-collections/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/b2pweb%2Fbdf-collections/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/b2pweb%2Fbdf-collections/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/b2pweb","download_url":"https://codeload.github.com/b2pweb/bdf-collections/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":230340254,"owners_count":18211187,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["collections","functional","java-streams"],"created_at":"2024-12-18T21:19:23.004Z","updated_at":"2024-12-18T21:19:23.660Z","avatar_url":"https://github.com/b2pweb.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Collections\n\nImplementation of commons collections, with java-like stream to apply transformations.\n\n[![build](https://github.com/b2pweb/bdf-collections/actions/workflows/php.yml/badge.svg)](https://github.com/b2pweb/bdf-collections/actions/workflows/php.yml)\n[![codecov](https://codecov.io/github/b2pweb/bdf-collections/branch/master/graph/badge.svg?token=VOFSPEWYKX)](https://app.codecov.io/github/b2pweb/bdf-collections)\n[![Packagist Version](https://img.shields.io/packagist/v/b2pweb/bdf-collections.svg)](https://packagist.org/packages/b2pweb/bdf-collections)\n[![Total Downloads](https://img.shields.io/packagist/dt/b2pweb/bdf-collections.svg)](https://packagist.org/packages/b2pweb/bdf-collections)\n[![Type Coverage](https://shepherd.dev/github/b2pweb/bdf-collections/coverage.svg)](https://shepherd.dev/github/b2pweb/bdf-collections)\n\n- [Installation](#installation-with-composer)\n- [Usage](#usage)\n    - [Collections](#collections-1)\n        - [ArrayCollection](#arraycollection)\n        - [OrderedCollection](#orderedcollection)\n        - [HashSet](#hashset)\n        - [HashTable](#hashtable)\n    - [Streams](#streams)\n        - [Usage](#usage-1)\n        - [MutableArrayStream](#mutablearraystream)\n    - [Optional](#optional)\n\n# Installation with composer\n\n```\ncomposer require b2pweb/bdf-collections\n```\n\n# Usage\n\n## Collections\n\nAll collections implements the `Bdf\\Collection\\CollectionInterface` interface.\n\nA collection is a simple bag of elements, with a restricted set of methods :\n- `add(mixed $element)` Add the element to the collection. The implementation may reject the operation, and returns false.\n- `addAll(iterator $elements)` Equivalent to `foreach ($elements as $element) { $collection-\u003eadd($element); }`.\n- `clear()` Remove all elements.\n- `replace(iterable $elements)` Clear and replace all elements.\n- `empty()` Check if the collection has no elements.\n- `contains($element, bool $strict = false)` Check if the collection contains the given element. If `$strict` is set to `true`, use strict comparison operator `===`.\n- `forEach(callable $callback)` Iterates over all elements, using a callback.\n- `toArray()` Convert the collection to an array.\n- And inherited methods of `IteratorAggregate`, `Countable` and `Streamable`\n\nThe base behavior of collections is extended by other interfaces :\n- `OrderedCollectionInterface` : Ensure that all elements of the collection are ordered. Add (or modify) methods :\n    - `contains($element, bool $strict = false)` Perform a binary search. The complexity of the call is O(log(n)) instead of O(n) on a simple collection.\n    - `search($element, bool $strict = false)` Get the element position. Works like `contains($element, bool $strict = false)` but return the position instead of `true`. The expression `$element == $collection-\u003eat($collection-\u003esearch($element))` is always `true` when `$element` exists.\n    - `at(int $position)` Get an element at the given position.\n    - `ArrayAccess` methods, expects `offsetSet()`. Works with the position as offset.\n- `SetInterface` : Ensure that the collection no not contains any duplicated elements. Add (or modify) methods :\n    - `add($element)` If the collection already contains the element, will return false, ignore the operation.\n    - `addAll(iterable $elements)` Return `false` is at least on element is already added.\n    - `lookup($element)` Find the corresponding elements stored into the Set.\n- `TableInterface` Add the key handling for modifying, or accessing elements :\n    - `set($key, $value)` Set a value at the given key.\n    - `get($key)` Get a value at the given key.\n    - `hasKey($key)` Check if a key exists.\n    - `keys()` Get all keys of the table.\n    - `values()` Get all values as array. This is equivalent to `iterator_to_array($collection)`\n    - `forEach(callable $callback)` Iterates over elements, but add the key as second argument of the callback.\n    - `ArrayAccess` methods    \n\n### ArrayCollection\n\nThe `Bdf\\Collection\\ArrayCollection` is the base implementation of `TableInterface` using an inner PHP array.\nIt has great performances but do not handle complex key types, or optimised search.\n\nUse as collection :\n```php\n\u003c?php\n$collection = new ArrayCollection(['foo']);\n\n$collection-\u003econtains('foo'); // true\n$collection-\u003econtains('bar'); // false\n\n$collection-\u003eadd('bar');\n$collection-\u003econtains('bar'); // true\n$collection-\u003eremove('bar');\n$collection-\u003econtains('bar'); // false\n\n$collection-\u003eadd(42);\n$collection-\u003econtains('42', true); // false\n$collection-\u003econtains(42, true); // true\n\n// Print \"foo 42\"\n$collection-\u003eforEach (function ($value) {\n    echo $value, ' ';\n});\n\n// Same as above\nforeach ($collection as $value) {\n    echo $value, ' ';\n}\n```\n\nUse as table :\n```php\n\u003c?php\n$table = new ArrayCollection(['foo' =\u003e 'bar']);\n\n// Using methods\n$table-\u003econtains('bar'); // true\n$table-\u003ehasKey('foo'); // true\n$table-\u003eget('foo'); // \"bar\"\n\n$table-\u003eset('value', 42);\n$table-\u003econtains(42); // true\n\n// Using array access\nisset($table['value']); // true\n$table['value']; // 42\n\n$table-\u003evalues(); // ['bar', 42]\n$table-\u003ekeys(); // ['foo', 'value]\n\n// Print \"foo=bar value=42\"\n$table-\u003eforEach (function ($value, $key) {\n    echo $key, '=', $value, ' ';\n});\n\n// Same as above\nforeach ($table as $key =\u003e $value) {\n    echo $key, '=', $value, ' ';\n}\n```\n\n### OrderedCollection\n\nSimple implementation of `OrderedCollectionInterface`. Do not sorts elements on modification, but only on access.\n\nUsage :\n\n```php\n\u003c?php\n$collection = new OrderedCollection();\n\n$collection-\u003eaddAll([4, 9, 2, 7]);\n\n$collection-\u003econtains(9); // true\n$collection-\u003esearch(4); // 1\n$collection-\u003eat(2); // 7\n$collection-\u003etoArray(); // [2, 4, 7, 9]\n\n$collection-\u003eremove(7);\n$collection-\u003etoArray(); // [2, 4, 9]\n\n// Array access\n$collection[0]; // 2\nisset($collection[9]); // false : check the existence of the offset\nisset($collection[1]); // true\n$collection[] = 5; // Add the element 5\nunset($collection[2]); // Remove the 3rd element (5)\n\n// Prints 0=2 4=1 9=2\n$collection-\u003eforEach(function ($element, $position) {\n    echo \"$position=$element \";\n});\n\n// Same as above\nforeach ($collection as $position =\u003e $element) {\n    echo \"$position=$element \";\n}\n\n// A custom comparator can also be used\n$collection = new OrderedCollection(function ($a, $b) {\n    return $a-\u003ecompute() - $b-\u003ecompute();\n});\n```\n\n### HashSet\n\nA `SetInterface` implementation using an hash function for check the uniqueness of elements.\n**Note: Unlike common HashSet implementations, like in java, only the hash code is used on comparison, and the equal operator is never used.** \n\n```php\n\u003c?php\n\n$set = new HashSet();\n\n$set-\u003eadd('foo'); // true\n$set-\u003eadd('foo'); // false : already added\n$set-\u003econtains('foo'); // true\n$set-\u003econtains('not found'); // false\n\n// Works also with array or objects\n$set-\u003eadd(['foo' =\u003e 'bar']);\n\n$obj = new stdClass();\n$set-\u003eadd($obj);\n\n$set-\u003elookup(new stdClass())-\u003eget() === $obj; // Get the stored element, which is equals with the parameter\n$set-\u003eloopup('not found')-\u003eempty(); // true : An empty optional is returned if the element is not found\n\n$objectSet = HashSet::spl(); // Use spl_object_hash() as hash function\n\n$obj1 = new stdClass();\n$obj2 = new stdClass();\n\n$objectSet-\u003eadd($obj1);\n$objectSet-\u003econtains($obj1); // true\n$objectSet-\u003econtains($obj2); // false : not the same reference, hash is different\n```\n\n### HashTable\n\nA more powerful and flexible implementation of `TableInterface`, using an hash function. This implementation is about 2 times slower than `ArrayCollection`.\nUnlike `ArrayCollection`, complex key types are supported (like objects).\n\n**Note: toArray() may failed if complex keys are used.**\n\nUsage :\n```php\n\u003c?php\n// Use HashTable with multiple-keys indexing using array\n$table = new HashTable();\n\n$table[[123, 'aze']] = new Entity(1);\n$table[[456, 'rty']] = new Entity(2);\n\n$table[[123, 'aze']]; // Returns Entity(1)\n\n// Use object as key\n$table[new Key()] = 'value';\n\n$table-\u003etoArray(false); // Associative array is not possible : return in form [ [key, value], ... ]\n\n// Create a case insensitive table by registering a custom hash function\n$ciTable = new HashTable('strtolower'); // Transform keys to lower case\n\n$ciTable-\u003eset('Foo', 'bar');\n$ciTable-\u003eget('FOO'); // 'bar'\n```\n\n## Streams\n\nStreams are used to transform collections elements. The streams implements `Iterator`, and can be used on a `foreach`.\nEach stream methods will return a new Stream instance :\n- `map(callable $transformer)` Apply $transformer to each values of the stream.\n- `mapKey(callable $function)` Apply $function to each values of the stream for generates keys.\n- `filter(callable $predicate)` Filter stream elements that are rejected by the predicate.\n- `distinct(callable $hashFunction = null)` Filter stream elements to get only distinct elements. A custom hash function can be used.\n- `sort(callable $comparator = null, bool $preserveKeys = false)` Order stream elements.\n- `concat(StreamInterface $stream, bool $preserveKeys = true)` Concatenate a new stream after the current stream.\n- `flatMap(callable $transformer, bool $preserveKeys = false)` Create a stream resulting of concatenation of each elements content extracted by $transformer.\n- `skip(int $count)` Skip the $count first elements of the stream.\n- `limit(int $count, int $offset = 0)` Limit the number of elements of the stream.\n- `forEach(callable $consumer)` Iterate over all stream elements.\n- `toArray(bool $preserveKeys = true)` Aggregate the stream to an array.\n- `first()` Get the first element of the stream.\n- `reduce(callable $accumulator, $initial = null)` Reduce all elements of the stream into a single value.\n- `collect(CollectorInterface $collector)` Collect all elements into a single value.\n- `matchAll(callable $predicate)` Check if all elements of the stream match with the predicate.\n- `matchOne(callable $predicate)` Check if at least one element of the stream match with the predicate.\n\n### Usage\n\n```php\n$stream = Streams::wrap([7, 4, 9]);\n\n// [ 10 =\u003e 8, 16 =\u003e 14, 20 =\u003e 18]\n$stream\n    -\u003esort()\n    -\u003emap(function ($element) { return $element * 2; })\n    -\u003emapKey(function ($element) { return $element + 2; })\n    -\u003etoArray()\n;\n```\n\n### MutableArrayStream\n\nThe stream `MutableArrayStream` is an implementation of `StreamInterface` for simple PHP array. Unlike other streams, all transformations are applied on the method call, and `$this` is returned instead of a new stream instance.\nReduce the overhead of the streams, for get better performances, but some methods has different behavior.\n\nUsage :\n```php\n$collection = new ArrayCollection([...]);\n\n$stream = $collection-\u003emutableStream(); // Get a mutable stream from an ArrayCollection\n$stream = new MutableArrayStream([...]); // Or creates using constructor\n\n// And use like other streams\n$stream\n    -\u003emap(...)\n    -\u003efilter(...)\n    -\u003ecollect(...)\n;\n```\n\n## Optional\n\nThe `Bdf\\Collection\\Util\\Optional` is used to replace `null` value and null object. It permit to creates a simple null object. Methods :\n- `filter(callable $predicate)` Filter the optional value.\n- `map(callable $transformer)` Transform the element if it's present.\n- `apply(callable $consumer)` Apply the consumer on the element if it's present.\n- `or($value)` Get the current Optional value if it's present, or the parameter value if not present.\n- `orThrows($exception = RuntimeException::class)` Get the current value if present, or throws an exception.\n- `orSupply(callable $supplier)` Get the current value if present, or return the supplier result.\n- `present()` Check if the Optional value is present or not.\n- `get()` Get the current stored value.\n- Magic methods, which delegates to the inner object, and wrap the return value into an optional\n\nUsage :\n```php\n\u003c?php\n\n// Creates the optional\nOptional::empty(); // \"Null\" optional\nOptional::of($myValue); // Wrap $myValue into an Optional. The value must not be null\nOptional::nullable($myValue); // Wrap $myValue into an Optional. The value may be null\n\nOptional::empty()-\u003epresent(); // false\nOptional::of(42)-\u003epresent(); // true\n\n// Creates a simple null object\n$myNullObject = Optional::nullable($person);\n\n$myNullObject-\u003efirstName()-\u003eor('undefined'); // Call $person-\u003efirstName() if present, and get the return value, or return \"undefined\"\nisset($myNullObject-\u003emyProp); // Check if property myProp exists into $person \n\n$myNullObject-\u003estream(); // Creates a singleton or empty stream with the wrapped element.\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fb2pweb%2Fbdf-collections","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fb2pweb%2Fbdf-collections","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fb2pweb%2Fbdf-collections/lists"}