如果一个 Iterator 已被部分或完全遍历,再对其调用 iterator_count() 会返回剩余元素数量或0。
错误示例:
<span><span><span class="hljs-variable">$it</span></span><span> = </span><span><span class="hljs-keyword">new</span></span><span> </span><span><span class="hljs-built_in">ArrayIterator</span></span><span>([</span><span><span class="hljs-number">1</span></span><span>, </span><span><span class="hljs-number">2</span></span><span>, </span><span><span class="hljs-number">3</span></span><span>, </span><span><span class="hljs-number">4</span></span><span>]);
</span><span><span class="hljs-variable">$it</span></span><span>-></span><span><span class="hljs-title function_ invoke__">next</span></span><span>(); </span><span><span class="hljs-comment">// 移动了一步</span></span><span>
</span><span><span class="hljs-variable">$count</span></span><span> = </span><span><span class="hljs-title function_ invoke__">iterator_count</span></span><span>(</span><span><span class="hljs-variable">$it</span></span><span>); </span><span><span class="hljs-comment">// 返回 3 而不是 4</span></span><span>
</span></span>
解决方案:
在调用 iterator_count() 之前,先重置迭代器:
<span><span><span class="hljs-variable">$it</span></span><span> = </span><span><span class="hljs-keyword">new</span></span><span> </span><span><span class="hljs-built_in">ArrayIterator</span></span><span>([</span><span><span class="hljs-number">1</span></span><span>, </span><span><span class="hljs-number">2</span></span><span>, </span><span><span class="hljs-number">3</span></span><span>, </span><span><span class="hljs-number">4</span></span><span>]);
</span><span><span class="hljs-variable">$it</span></span><span>-></span><span><span class="hljs-title function_ invoke__">rewind</span></span><span>(); </span><span><span class="hljs-comment">// 重置指针</span></span><span>
</span><span><span class="hljs-variable">$count</span></span><span> = </span><span><span class="hljs-title function_ invoke__">iterator_count</span></span><span>(</span><span><span class="hljs-variable">$it</span></span><span>); </span><span><span class="hljs-comment">// 返回 4</span></span><span>
</span></span>
iterator_count() 会完全遍历迭代器。如果数据集庞大或迭代器中包含复杂逻辑,可能引发严重的性能问题。
示例:
<span><span><span class="hljs-variable">$it</span></span><span> = </span><span><span class="hljs-keyword">new</span></span><span> </span><span><span class="hljs-built_in">InfiniteIterator</span></span><span>(</span><span><span class="hljs-keyword">new</span></span><span> </span><span><span class="hljs-built_in">ArrayIterator</span></span><span>([</span><span><span class="hljs-number">1</span></span><span>, </span><span><span class="hljs-number">2</span></span><span>, </span><span><span class="hljs-number">3</span></span><span>]));
</span><span><span class="hljs-variable">$count</span></span><span> = </span><span><span class="hljs-title function_ invoke__">iterator_count</span></span><span>(</span><span><span class="hljs-variable">$it</span></span><span>); </span><span><span class="hljs-comment">// 永远不会结束</span></span><span>
</span></span>
解决方案:
仅对有限、已知范围的数据使用。
避免在无限或大型数据结构中直接调用。
考虑实现自定义计数逻辑。
使用前确保迭代器未被部分遍历,或通过 rewind() 重置指针。
对不可重用的迭代器(如生成器)避免直接调用 iterator_count(),可使用 iterator_to_array() 转换后再统计。
避免在无限或高消耗的迭代器上调用该函数,要先评估执行的代价。
写测试代码验证行为,尤其是对第三方库返回的 Traversable 类型对象。