迭代器模式
1
迭代器模式/原理:利用迭代器 迭代/循环遍历 可迭代对象中的数据集合。 原理上是利用迭代器的。
而且不是一次性将全部读取到内存中,而是一个一个读取,用过的内存再被覆盖,这样明显不会占用太多内存。迭代器并不是一次性读出所有数据,而是一次一次读出.
迭代器模式提供一种方法顺序访问一个聚合对象中的各种元素,而又不暴露该对象的内部表示。
一般意义上/广义上的:
可迭代对象:1.本身中拥有集合。2一般 拥有或可以得到迭代器的对象(因为要通过迭代器去访问数据集合) 3.可通过迭代器访问可迭代对象中的数据集合 或 可对对象本身直接进行for的对象(实际上也是通过获取可迭代对象的迭代器去迭代其中的集合,一种语法糖罢了)。 <==> 可迭代/循环 (其中的数据集合)的对象 <==> 可for/while 的对象(使用for while 或 直接在for foreach 中使用的)
迭代器: 一般指,可以对可迭代对象/数据集合 进行迭代(循环)处理的对象。通过迭代器 可以迭代(循环)遍历可迭代对象中的数据集合。所以 一般迭代器中是拥有或可访问到可迭代对象中的数据集合或者本身也是可迭代对象(自然就能访问到可迭代对象中的数据集合),而且会维护一个index和集合个数。
迭代器对象本身不能用于for中(不一定,有的具体语言语法是迭代器本身也是可迭代对象,因此也可以直接用于for)。 但是可以通过迭代器去迭代访问集合中的数据。
我们编程中直接对外的接口为可迭代对象(因为最直接的表现拥有数据集合,因此直接与我们接触的就是可迭代对象)。 通过可迭代对象 可以获得 迭代器。 通过迭代器 可以迭代访问可迭代对象中的数据集合。
迭代访问可迭代对象中的数据集合: 1.通过获取迭代器,从而迭代访问可迭代对象中的数据集合。 2.通过for直接使用可迭代对象(原理也是1,实际上一种语法糖)。
[广义的,狭义的 可迭代对象 迭代器。 广义上一般 不是某种具体的语法。 狭义的 一般是语言中特指的类,符合广义的含义 的类对象。一般在某个语言中说 可迭代对象 迭代器是狭义的指该语言中狭义上的迭代器 可迭代对象,一般是符合特殊要求的类]
注意,具体语言中的可迭代对象和迭代器,如果有语法所谓的可迭代对象 迭代器, 那么这个可迭代对象和迭代器一般是指 狭义上的迭代器 可迭代对象,是某种特殊要求的类。
通过demo来体会下迭代器模式,可迭代对象, 迭代器。
关键:
1.类的设计
可迭代对象设计:a.可迭代对象本身拥有数据集合。b.通过可迭代对象可以获取到迭代器(因此可迭代对象应该能获取到或持有迭代器)。
迭代器设计:a.通过迭代器可以访问到可迭代对象(因此可迭代器要能访问可迭代对象的能力) b.迭代的访问,持有idx指针或其他能表明数据集合状态的值。维持状态、进度,也即用到索引。
2.对外接口使用(通过可迭代对象,获取迭代器,通过迭代器访问可迭代对象(中的数据集合)或直接在for中使用可迭代对象本身)。
demo:
C
Java
Python
https://cloud.tencent.com/developer/article/1805426
https://www.jianshu.com/p/a40d5a42d643
https://blog.csdn.net/jxqingge/article/details/81296465
2
package cn.bjsxt.interator;
/**
* 简化迭代器原理
* hasNext
* next
* @author Administrator
*
*/
public class MyArrayList {
private String[] elem = {"a","b","c","d","e","f","g"};
private int size = elem.length;
private int curror = -1;
/**
* 判断是否存在下一个元素
* @return
*/
public boolean hasNext() {
return curror+1 < size; //指向下一个元素
}
/**
* 获取下一个元素
*/
public String next() {
curror++; //移动一次
return elem[curror];
}
public static void main(String[] args) {
MyArrayList list = new MyArrayList();
while(list.hasNext()) {
System.out.println(list.next());
}
}
}
严格意义上来将,MyArrayList 这个只是用到了迭代器模式,MyArrayList并不是定义上的可迭代对象。
可迭代对象在不同语言中的实现有不同的要求(语法要求)。
Java中是指 要必须实现 Iterable 接口。python中是实现继承Iterable类或实现__iter__ 方法 。才能称之为可迭代对象。 可迭代对象 特征: 对象本身可以直接用于 for ,增强的foreach 的语法中。(通常本身也可以获取到迭代器,或 持有迭代器引用)
迭代器在不同语言中的实现有不同的要求。
Java中是指要必须实现Iterator接口(该接口有两个方法 hasnext() next()). Python中是继承Iterator类或实现__iter__和__next__。 迭代器特征: 对象本身不能用于for中。 但是可以通过迭代器去迭代访问集合中的数据。
ps:java中仅仅自己实现hasnext next的类 并不能称之为迭代器 或 可迭代对象,那仅仅能称之为可迭代模式。
public interface Iterator<E> {
/**
* Returns {@code true} if the iteration has more elements.
* (In other words, returns {@code true} if {@link #next} would
* return an element rather than throwing an exception.)
*
* @return {@code true} if the iteration has more elements
*/
boolean hasNext();
/**
* Returns the next element in the iteration.
*
* @return the next element in the iteration
* @throws NoSuchElementException if the iteration has no more elements
*/
E next();
...
}
public interface Iterable<T> {
/**
* Returns an iterator over elements of type {@code T}.
*
* @return an Iterator.
*/
Iterator<T> iterator();
/**
* Performs the given action for each element of the {@code Iterable}
* until all elements have been processed or the action throws an
* exception. Unless otherwise specified by the implementing class,
* actions are performed in the order of iteration (if an iteration order
* is specified). Exceptions thrown by the action are relayed to the
* caller.
*
* @implSpec
* <p>The default implementation behaves as if:
* <pre>{@code
* for (T t : this)
* action.accept(t);
* }</pre>
*
* @param action The action to be performed for each element
* @throws NullPointerException if the specified action is null
* @since 1.8
*/
default void forEach(Consumer<? super T> action) {
Objects.requireNonNull(action);
for (T t : this) {
action.accept(t);
}
}
/**
* Creates a {@link Spliterator} over the elements described by this
* {@code Iterable}.
*
* @implSpec
* The default implementation creates an
* <em><a href="Spliterator.html#binding">early-binding</a></em>
* spliterator from the iterable's {@code Iterator}. The spliterator
* inherits the <em>fail-fast</em> properties of the iterable's iterator.
*
* @implNote
* The default implementation should usually be overridden. The
* spliterator returned by the default implementation has poor splitting
* capabilities, is unsized, and does not report any spliterator
* characteristics. Implementing classes can nearly always provide a
* better implementation.
*
* @return a {@code Spliterator} over the elements described by this
* {@code Iterable}.
* @since 1.8
*/
default Spliterator<T> spliterator() {
return Spliterators.spliteratorUnknownSize(iterator(), 0);
}
}
python中 迭代器:1.实现__iter__和__next__(iter__返回迭代器本身)。 或者 2. 继承Iterator类(该类也是有__iter__和__next)。
python中 可迭代对象:1.实现__iter__ 方法 (返回一个迭代器). 或者 2.继承Iteratble类(该类也是有__iter__)。
从python 中定义来看,python中的迭代器也是可迭代对象。 可迭代对象不一定是迭代器。 所以python中迭代器本身也可以直接用于for。
iter方法:
https://blog.csdn.net/sunjintaoxxx/article/details/122060513
from collections import Iterator, Iterable
@runtime_checkable
class Iterable(Protocol[_T_co]):
@abstractmethod
def __iter__(self) -> Iterator[_T_co]: ...
@runtime_checkable
class Iterator(Iterable[_T_co], Protocol[_T_co]):
@abstractmethod
def __next__(self) -> _T_co: ...
def __iter__(self) -> Iterator[_T_co]: ...
Java,pyhton 中的可迭代对象 都可以得到 迭代器。(有的方式是直接持有迭代器对象)。
由于在C中没有相应的语法要求,迭代器 可迭代对象(由于没有语法支持,无法让对象本身用于for), 不能在语法层面得到支持。 但是C也可以像java那样自定义构造一个迭代器,然后可迭代对象中持有迭代器(虽然这个可迭代器对象无法直接用于for,但是基本思想 框架是如此的,也是迭代器模式).