生成器提供了一种更容易的方法来实现简单的对象迭代,相比较定义类实现 Iterator 接口的方式,性能开销和复杂性大大降低。
yield
的理解:yield关键字暂停当前方法,且返回值给上一级处理。当上一级处理完毕继续遍历时,继续冲上次暂停的地方继续执行。
<?php
/**
* 生成器
*
* @author tangbo<admin@tbphp.net>
*/
namespace App;
use Generator;
class RangeGenerator
{
private $len = 0;
public function __construct(int $len)
{
$this->len = $len;
}
public function range(): Generator
{
for ($i = 0; $i <= $this->len; $i++) {
yield $i;
}
}
}
<?php
use App\RangeGenerator;
use App\RangeIterator;
use PHPUnit\Framework\TestCase;
class RangeGeneratorTest extends TestCase
{
private $size = 50000;
/**
* 测试原始range方法
*/
public function testOldrange(): void
{
$this->result(memory_get_usage(), range(0, $this->size));
}
/**
* 测试yield关键字生成器方法
*/
public function testRange(): void
{
$this->result(memory_get_usage(), (new RangeGenerator($this->size))->range());
}
private function result($start, $range): void
{
foreach ($range as $v) {
echo $v;
}
echo PHP_EOL;
echo '内存:' . (memory_get_usage() - $start) . PHP_EOL;
}
}
<?php
/**
* Description
*
* @author tangbo<admin@tbphp.net>
*/
namespace App;
use Iterator;
class RangeIterator implements Iterator
{
private $size;
private $key;
public function __construct($size)
{
$this->size = $size;
}
public function current()
{
return $this->key;
}
public function next()
{
$this->key++;
}
public function key()
{
return $this->key;
}
public function valid()
{
return $this->key <= $this->size;
}
public function rewind()
{
$this->key = 0;
}
}
/**
* 测试迭代器
*/
public function testIrange(): void
{
$this->result(memory_get_usage(), new RangeIterator($this->size));
}