IteratorAggregate
是实现迭代器的一种简单方法。缺点是您无法添加 、 等方法,因为它们在正常遍历期间不会被调用。next()
key()
foreach
如果需要实现自定义方法,则需要实现 或 (更容易) 扩展 .OuterIterator
IteratorIterator
优点是速度快,它比它的替代品快得多。它的问题是...尽管名称如此,但它不是迭代器,而是可遍历的(所以再次,没有下一个,键,当前,有效,倒带方法)。IteratorAggregate
这是一个简单的基准测试,我在我可怜的笔记本电脑上运行,每个,每次都有100万次迭代,并且使用和:(还要注意Ag aggregate下一个
方法中的回声
:没有打印“x”,证明它永远不会被调用)IteratorAggregate
IteratorIterator
OuterIterator
iterator_to_array
foreach
$ repeat 3 php benchIterator.php
------------------------------------
Outer_ToArray: 569.61703300476 ms
Aggregate_ToArray: 552.38103866577 ms
IteratorIt_ToArray: 546.95200920105 ms
Outer_Foreach: 1679.8989772797 ms
IteratorIt_Foreach: 1019.6850299835 ms
Aggregate_Foreach: 367.35391616821 ms
------------------------------------
Outer_ToArray: 570.75309753418 ms
Aggregate_ToArray: 544.40784454346 ms
IteratorIt_ToArray: 555.06300926208 ms
Outer_Foreach: 1682.2130680084 ms
IteratorIt_Foreach: 988.21592330933 ms
Aggregate_Foreach: 356.41598701477 ms
------------------------------------
Outer_ToArray: 566.06101989746 ms
Aggregate_ToArray: 543.1981086731 ms
IteratorIt_ToArray: 546.28610610962 ms
Outer_Foreach: 1663.2289886475 ms
IteratorIt_Foreach: 995.28503417969 ms
Aggregate_Foreach: 356.16087913513 ms
以下是我用于基准测试的代码:
<?php
class Aggregate implements \IteratorAggregate
{
protected $var;
public function __construct($var = null)
{
if (is_array($var)) {
$this->var = new ArrayIterator($var);
}
if ($var instanceof \Traversable) {
$this->var = $var;
}
}
public function next()
{
echo 'x';
}
public function toArray()
{
return iterator_to_array($this->var, true);
}
public function getIterator()
{
return $this->var;
}
}
class Outer implements \OuterIterator
{
protected $var;
public function __construct($var = null)
{
if (is_array($var)) {
$this->var = new ArrayIterator($var);
}
if ($var instanceof \Traversable) {
$this->var = $var;
}
}
public function toArray()
{
return iterator_to_array($this->var, true);
}
public function getInnerIterator()
{
return $this->var;
}
public function current()
{
return $this->var->current();
}
public function next()
{
$this->var->next();
}
public function key()
{
return $this->var->key();
}
public function valid()
{
return $this->var->valid();
}
public function rewind()
{
$this->var->rewind();
}
}
class IteratorIt extends IteratorIterator
{
public function __construct($var = null)
{
if (is_array($var)) {
$var = new ArrayIterator($var);
}
parent::__construct($var);
}
public function toArray()
{
return iterator_to_array($this->getInnerIterator(), true);
}
public function getIterator()
{
return $this->getInnerIterator();
}
}
function bench($name, $test)
{
echo "$name: ";
$start = microtime(true);
$test();
$time = microtime(true);
$time -= $start;
echo ($time * 1000) . ' ms' . PHP_EOL;
}
$max = 1e6;
$array = range (1, 1e6);
$testSuites = [
'Outer_ToArray' => function () use ($max, $array) {
$iterator = new Outer($array);
$r = $iterator->toArray();
},
'Aggregate_ToArray' => function () use ($max, $array) {
$iterator = new Aggregate($array);
$r = $iterator->toArray();
},
'IteratorIt_ToArray' => function () use ($max, $array) {
$iterator = new IteratorIt($array);
$r = $iterator->toArray();
},
'Outer_Foreach' => function () use ($max, $array) {
$iterator = new Outer($array);
foreach ($iterator as $k => $v)
{
}
},
'IteratorIt_Foreach' => function () use ($max, $array) {
$iterator = new IteratorIt($array);
foreach ($iterator as $k => $v)
{
}
},
'Aggregate_Foreach' => function () use ($max, $array) {
$iterator = new Aggregate($array);
foreach ($iterator as $k => $v)
{
}
},
];
echo '------------------------------------'.PHP_EOL;
foreach ($testSuites as $name => $test) {
bench($name, $test);
}