迭代器模式是數(shù)據(jù)訪問遍歷的一種行為模式泽疆。java中List户矢、Set、Map 等都包含了迭代器殉疼。迭代器提供一個(gè)對(duì)象來順序訪問聚合對(duì)象中的一系列數(shù)據(jù)梯浪,而不暴露聚合對(duì)象的內(nèi)部表示捌年。迭代器模式的優(yōu)點(diǎn):
- 無須暴露聚合對(duì)象的內(nèi)部表示
- 遍歷任務(wù)交由迭代器完成,簡化聚合類
- 遍歷的方式可擴(kuò)展
模式結(jié)構(gòu)
迭代器模式主要包含以下角色挂洛。
- 抽象聚合(Aggregate)角色:定義存儲(chǔ)礼预、添加、刪除聚合對(duì)象以及創(chuàng)建迭代器對(duì)象的接口虏劲。
- 具體聚合(ConcreteAggregate)角色:實(shí)現(xiàn)抽象聚合類托酸,返回一個(gè)具體迭代器的實(shí)例。
- 抽象迭代器(Iterator)角色:定義訪問和遍歷聚合元素的接口柒巫,通常包含 hasNext()励堡、first()、next() 等方法吻育。
- 具體迭代器(Concretelterator)角色:實(shí)現(xiàn)抽象迭代器接口中所定義的方法念秧,完成對(duì)聚合對(duì)象的遍歷,記錄遍歷的當(dāng)前位置布疼。
源碼導(dǎo)讀
集合類的迭代器我們沒少用,我們來看看它的相關(guān)源碼吧币狠,以 ArrayList
為例游两,它就是一個(gè)collection的具體聚合,其方法 iterator()
便是獲取迭代器的方法:
public Iterator<E> iterator() {
return new Itr();
}
z這個(gè) Itr
是它的內(nèi)部類:
private class Itr implements Iterator<E> {
int cursor; // index of next element to return
int lastRet = -1; // index of last element returned; -1 if no such
int expectedModCount = modCount;
public boolean hasNext() {
return cursor != size;
}
@SuppressWarnings("unchecked")
public E next() {
checkForComodification();
int i = cursor;
if (i >= size)
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length)
throw new ConcurrentModificationException();
cursor = i + 1;
return (E) elementData[lastRet = i];
}
// 部分源碼省略
}
它的私有內(nèi)部類實(shí)現(xiàn)了 Iterator
接口:
public interface Iterator<E> {
boolean hasNext();
E next();
default void remove() {
throw new UnsupportedOperationException("remove");
}
default void forEachRemaining(Consumer<? super E> action) {
Objects.requireNonNull(action);
while (hasNext())
action.accept(next());
}
}
這就是一個(gè)迭代器的抽象接口漩绵。定義了對(duì)聚合對(duì)象的訪問方法贱案。
這里說一下設(shè)計(jì)亮點(diǎn) Itr
,它是個(gè)私有的內(nèi)部類止吐;這樣做的好處是做到了足夠的約束宝踪,避免使用者去以不合理的方式創(chuàng)建迭代器,并且可以自由的訪問外部類的私有屬性碍扔, 這樣的設(shè)計(jì)方式同樣適合建造者模式瘩燥。
我們簡單分析下 Itr
對(duì)外部類屬性的遍歷 它的三個(gè)屬性值標(biāo)記遍歷的相關(guān)信息。
int cursor; // index of next element to return
int lastRet = -1; // index of last element returned; -1 if no such
int expectedModCount = modCount;
我們看 Itr.next()
方法不同,Object[] elementData = ArrayList.this.elementData
就是獲取外部類對(duì)象的數(shù)據(jù)厉膀,這個(gè)elementData
就是實(shí)際存儲(chǔ)我們數(shù)據(jù)的對(duì)象,所以說ArrayList的底層是數(shù)組二拐;這里有個(gè)有意思的冷知識(shí) transient
關(guān)機(jī)鍵服鹅,在 ArrayList
中 它屬性是這樣定義的:
transient Object[] elementData
這個(gè)關(guān)鍵字修飾的屬性,在序列化對(duì)象的時(shí)候百新,這個(gè)屬性不會(huì)被序列化企软,這么做的原因感興趣的可以自行百度,這里不做太多分析饭望。