php 迭代接口的作用

想了解一下迭代器的作用, 网上大部分资料都会提到说"能够让对象像数组一样循环", 问题是我直接循环对象也是可以的啊, 有什么不行呢, 顶多就是一些不可见的元素不会展示出来呗, 说白了这迭代器接口不就是和foreach循环一模一样么!

还有人说迭代器接口隐藏内部结构什么的,怎么隐藏啊, 目前功力太浅,实在摸不到这特性!

迭代器接口难道就这点用? 就是把原本的foreach循环给搞复杂? 既然很多项目都在用,那显然有我不知道的优点啊

哪位大神给点提示或资料, 不胜感激

阅读 6.7k
2 个回答

泻药,既然收到邀请,我就来回答一下吧;

其实,我曾经也觉得这种东西没什么卵用,弄一个迭代器出来,代码看起来挺复杂的,很多数据直接基于数组不就好了嘛,后来我才意识到,还是我太天真了。

接下来的东西,我凭我自己的理解来进行表述。

首先,一个迭代器其实就是一个迭代类,只不过是原生PHP提供了一层封装。而迭代器类的调用,如果我们手动调用的话,一次也只能执行一个步骤。然后说一下foreach这个东西,这个东西大家都知道是一个循环语句结构,PHP特有的,但是这个的作用也就是每次移动一次指针取数据,也就是说自动遍历整条数据。

假设如以下这个东西:

$data = [1,2,3];

我们不用foreach的话,要输出里面的每个子数据只能是这样:

echo $data[0];
echo $data[1];
echo $data[2];

嗯,也就是说,循环语句的目的就是减少了我们本身要写的代码,程序自动执行重复的逻辑结构,记住,是重复的逻辑结构,不是一模一样的流程。

然后,回过头来说迭代器,先来看整个迭代器的结构:

Iterator extends Traversable {
/* 方法 */
abstract public mixed current ( void )
abstract public scalar key ( void )
abstract public void next ( void )
abstract public void rewind ( void )
abstract public boolean valid ( void )
}

很清晰的看到,迭代器提供的是一整套操作子数据的接口,foreach也就每次可以通过next移动指针(当然,迭代器的指针具体移动需要我们自己实现),然后通过valid检查迭代是否可结束。

那么,这样子一个东西有什么作用呢?

  1. 也就是@JVVV提到的,可以处理一个庞大数据量的问题,减少内存,这个东西可以看这样子一套数据,假设有1亿条数据的数组,按传统的遍历,我需要把这套东西放到内存,然后用foreach遍历,但是如果是迭代器的话,我每次迭代的时候,移动一下指针,去硬盘上取这么一条数据就可以了。当然这个是一种假设情况,不用钻牛角尖。
  2. 另外一个就是一些特殊数据的遍历了。比如我要遍历一个对象,就特别有用。
  3. 还有就是有些数据需要手动进行遍历,不需要通过foreach一次性处理完的时候,也很有用。

哦,然后说一下,这个迭代器和foreach压根是两个不同的东西,foreach是提供对迭代器进行遍历的一个工具,而迭代器的遍历不一定需要依赖于foreach遍历。
对迭代器的遍历也可以通过while来遍历的,如:

while($iterator->valid()) {
    $iterator->next();
}

特别说明一下对对象的遍历,一般人觉得所谓的遍历对象就是对一个对象里的属性或者方法一个一个的取出来,然后做输出或者处理,实际上,这里的迭代器对对象的遍历并不是这个意思,可能这句话本身的描述有问题。举个例子:


class String implements Iterator {
    private $string;
    public function __construct($string)
    {
        $this->string = $this->strToArray($string);
    }
    private function strToArray($string,$l=0) {
        if ($l > 0) {
            $ret = array();
            $len = mb_strlen($string, "UTF-8");
            for ($i = 0; $i < $len; $i += $l) {
                $ret[] = mb_substr($string, $i, $l, "UTF-8");
            }
            return $ret;
        }
        return preg_split("//u", $string, -1, PREG_SPLIT_NO_EMPTY);
    }
    public function current()
    {
        return current($this->string);
    }
    public function next()
    {
        return next($this->string);
    }
    public function key()
    {
        key($this->string);
    }
    public function valid()
    {
        if(key($this->string) === null) {
            return false;
        } else {
            return true;
        }
    }
    public function rewind()
    {
        reset($this->string);
    }
}

$string = new String('这个是什么213jdjlf');

foreach ($string as $k => $v) {
    echo $v."\n";
}

这个是模拟java的字符串对象,java的字符串对象其实也实现了类似这样的一个迭代器接口,然后可以对字符串进行遍历。
同样的,以上PHP实现的字符串对象也是可以对这个字符串对象进行遍历。

迭代器和foreach最大的区别就是,迭代器返回给你的是一个函数,不调用它,他yield返回值给你。foreach中如果数组非常庞大,内存就会存在问题,但是迭代器不存在这个问题。你可以看一下鸟哥的这篇文章.
http://www.laruence.com/2015/...

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏