b2pweb / bdf-collections
具有Java 8流API的集合实现。
Requires
- php: ~7.1 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0
Requires (Dev)
- phpbench/phpbench: ~0.0|~1.0
- phpunit/phpunit: ~7.0|~8.0
- vimeo/psalm: ~4.15
README
实现commonscollections,带有类似Java流的转换应用。
使用composer安装
composer require b2pweb/bdf-collections
使用方法
集合
所有集合实现 Bdf\Collection\CollectionInterface
接口。
集合是元素的一个简单袋子,具有一组有限的方法
add(mixed $element)
将元素添加到集合中。实现可能拒绝操作,并返回false。addAll(iterator $elements)
等同于foreach ($elements as $element) { $collection->add($element); }
。clear()
删除所有元素。replace(iterable $elements)
清除并替换所有元素。empty()
检查集合是否没有元素。contains($element, bool $strict = false)
检查集合是否包含给定元素。如果$strict
设置为true
,则使用严格的比较运算符===
。forEach(callable $callback)
使用回调遍历所有元素。toArray()
将集合转换为数组。- 继承自
IteratorAggregate
、Countable
和Streamable
的方法
其他接口扩展了集合的基本行为
OrderedCollectionInterface
: 确保集合的所有元素都是有序的。添加(或修改)方法contains($element, bool $strict = false)
执行二分搜索。调用复杂度为O(log(n)),而不是简单集合的O(n)。search($element, bool $strict = false)
获取元素位置。类似于contains($element, bool $strict = false)
,但返回位置而不是true
。当$element
存在时,表达式$element == $collection->at($collection->search($element))
总是true
。at(int $position)
获取指定位置的元素。ArrayAccess
方法,期望offsetSet()
。使用位置作为偏移量。
SetInterface
: 确保集合不包含任何重复元素。添加(或修改)方法add($element)
如果集合已经包含该元素,则返回false,忽略操作。addAll(iterable $elements)
如果至少有一个元素已添加,则返回false。lookup($element)
查找存储在Set中的相应元素。
TableInterface
添加键处理以修改或访问元素set($key, $value)
在给定键处设置值。get($key)
在给定键处获取值。hasKey($key)
检查键是否存在。keys()
获取表的所有键。values()
获取所有值作为数组。这与iterator_to_array($collection)
等效。forEach(callable $callback)
遍历元素,但将键作为回调的第二个参数。ArrayAccess
方法
ArrayCollection
Bdf\Collection\ArrayCollection
是使用内部PHP数组实现的 TableInterface
的基本实现。它具有优异的性能,但不能处理复杂的键类型或优化搜索。
作为集合使用
<?php $collection = new ArrayCollection(['foo']); $collection->contains('foo'); // true $collection->contains('bar'); // false $collection->add('bar'); $collection->contains('bar'); // true $collection->remove('bar'); $collection->contains('bar'); // false $collection->add(42); $collection->contains('42', true); // false $collection->contains(42, true); // true // Print "foo 42" $collection->forEach (function ($value) { echo $value, ' '; }); // Same as above foreach ($collection as $value) { echo $value, ' '; }
作为表使用
<?php $table = new ArrayCollection(['foo' => 'bar']); // Using methods $table->contains('bar'); // true $table->hasKey('foo'); // true $table->get('foo'); // "bar" $table->set('value', 42); $table->contains(42); // true // Using array access isset($table['value']); // true $table['value']; // 42 $table->values(); // ['bar', 42] $table->keys(); // ['foo', 'value] // Print "foo=bar value=42" $table->forEach (function ($value, $key) { echo $key, '=', $value, ' '; }); // Same as above foreach ($table as $key => $value) { echo $key, '=', $value, ' '; }
OrderedCollection
对OrderedCollectionInterface
的简单实现。在修改时不会对元素进行排序,仅在访问时进行排序。
使用方法
<?php $collection = new OrderedCollection(); $collection->addAll([4, 9, 2, 7]); $collection->contains(9); // true $collection->search(4); // 1 $collection->at(2); // 7 $collection->toArray(); // [2, 4, 7, 9] $collection->remove(7); $collection->toArray(); // [2, 4, 9] // Array access $collection[0]; // 2 isset($collection[9]); // false : check the existence of the offset isset($collection[1]); // true $collection[] = 5; // Add the element 5 unset($collection[2]); // Remove the 3rd element (5) // Prints 0=2 4=1 9=2 $collection->forEach(function ($element, $position) { echo "$position=$element "; }); // Same as above foreach ($collection as $position => $element) { echo "$position=$element "; } // A custom comparator can also be used $collection = new OrderedCollection(function ($a, $b) { return $a->compute() - $b->compute(); });
HashSet
使用哈希函数检查元素唯一性的SetInterface
实现。**注意:与Java中的常见HashSet实现不同,这里仅在比较时使用哈希码,从不使用等号运算符。**
<?php $set = new HashSet(); $set->add('foo'); // true $set->add('foo'); // false : already added $set->contains('foo'); // true $set->contains('not found'); // false // Works also with array or objects $set->add(['foo' => 'bar']); $obj = new stdClass(); $set->add($obj); $set->lookup(new stdClass())->get() === $obj; // Get the stored element, which is equals with the parameter $set->loopup('not found')->empty(); // true : An empty optional is returned if the element is not found $objectSet = HashSet::spl(); // Use spl_object_hash() as hash function $obj1 = new stdClass(); $obj2 = new stdClass(); $objectSet->add($obj1); $objectSet->contains($obj1); // true $objectSet->contains($obj2); // false : not the same reference, hash is different
HashTable
使用哈希函数的更强大、更灵活的TableInterface
实现。此实现比ArrayCollection
慢约2倍。与ArrayCollection
不同,支持复杂键类型(如对象)。
注意:使用复杂键时,toArray()可能会失败。
使用方法
<?php // Use HashTable with multiple-keys indexing using array $table = new HashTable(); $table[[123, 'aze']] = new Entity(1); $table[[456, 'rty']] = new Entity(2); $table[[123, 'aze']]; // Returns Entity(1) // Use object as key $table[new Key()] = 'value'; $table->toArray(false); // Associative array is not possible : return in form [ [key, value], ... ] // Create a case insensitive table by registering a custom hash function $ciTable = new HashTable('strtolower'); // Transform keys to lower case $ciTable->set('Foo', 'bar'); $ciTable->get('FOO'); // 'bar'
Streams
使用流来转换集合元素。流实现Iterator
,并可用于foreach
循环。每个流方法都将返回一个新的流实例
map(callable $transformer)
将$transformer应用于流的每个值。mapKey(callable $function)
将$function应用于流的每个值以生成键。filter(callable $predicate)
过滤掉由谓词拒绝的流元素。distinct(callable $hashFunction = null)
过滤流元素以获取唯一元素。可以使用自定义哈希函数。sort(callable $comparator = null, bool $preserveKeys = false)
对流元素进行排序。concat(StreamInterface $stream, bool $preserveKeys = true)
在当前流之后连接一个新的流。flatMap(callable $transformer, bool $preserveKeys = false)
创建一个流,该流是$transformer提取的每个元素内容的连接。skip(int $count)
跳过流中的前$count个元素。limit(int $count, int $offset = 0)
限制流中的元素数量。forEach(callable $consumer)
遍历所有流元素。toArray(bool $preserveKeys = true)
将流聚合为数组。first()
获取流的第一个元素。reduce(callable $accumulator, $initial = null)
将流的所有元素归约为单个值。collect(CollectorInterface $collector)
将所有元素收集为单个值。matchAll(callable $predicate)
检查流中的所有元素是否与谓词匹配。matchOne(callable $predicate)
检查流中至少有一个元素与谓词匹配。
使用方法
$stream = Streams::wrap([7, 4, 9]); // [ 10 => 8, 16 => 14, 20 => 18] $stream ->sort() ->map(function ($element) { return $element * 2; }) ->mapKey(function ($element) { return $element + 2; }) ->toArray() ;
MutableArrayStream
流MutableArrayStream
是StreamInterface
的一个实现,用于简单的PHP数组。与其他流不同,所有转换都应用于方法调用,并返回$this而不是新的流实例。减少流的开销,以获得更好的性能,但某些方法的行为不同。
使用方法
$collection = new ArrayCollection([...]); $stream = $collection->mutableStream(); // Get a mutable stream from an ArrayCollection $stream = new MutableArrayStream([...]); // Or creates using constructor // And use like other streams $stream ->map(...) ->filter(...) ->collect(...) ;
Optional
Bdf\Collection\Util\Optional
用于替换null
值和null对象。它允许创建一个简单的null对象。方法
filter(callable $predicate)
过滤可选值。map(callable $transformer)
如果存在,则转换元素。apply(callable $consumer)
如果存在,则对元素应用消费者。or($value)
如果存在,则获取当前的Optional值,如果不存在,则获取参数值。orThrows($exception = RuntimeException::class)
如果存在,则获取当前值,如果不存在,则抛出异常。orSupply(callable $supplier)
如果存在,则获取当前值,如果不存在,则返回供应商的结果。present()
检查Optional值是否存在。get()
获取当前存储的值。- 魔法方法,将委托给内部对象,并将返回值包装在可选对象中
使用方法
<?php // Creates the optional Optional::empty(); // "Null" optional Optional::of($myValue); // Wrap $myValue into an Optional. The value must not be null Optional::nullable($myValue); // Wrap $myValue into an Optional. The value may be null Optional::empty()->present(); // false Optional::of(42)->present(); // true // Creates a simple null object $myNullObject = Optional::nullable($person); $myNullObject->firstName()->or('undefined'); // Call $person->firstName() if present, and get the return value, or return "undefined" isset($myNullObject->myProp); // Check if property myProp exists into $person $myNullObject->stream(); // Creates a singleton or empty stream with the wrapped element.