相信 “迭代” 對(duì)于Java程序員來(lái)說(shuō)并不陌生(當(dāng)然砾莱,其他語(yǔ)言的程序員也是如此)债鸡,在處理數(shù)據(jù)時(shí)箩兽,不可避免地會(huì)存在對(duì)數(shù)據(jù)的大量遍歷操作沃疮。對(duì)于我自己而言薇溃,學(xué)習(xí)使用Java語(yǔ)言?xún)赡陼r(shí)間雀费,對(duì)于“迭代”的概念還停留在 for:each
,for:i
的遍歷階段。今天用到了JDK 提供的迭代接口進(jìn)行 Java 集合的迭代痊焊,便決定作以筆記盏袄,留作以后學(xué)習(xí)。
普通 Java 集合迭代(遍歷)
迭代可以簡(jiǎn)單理解為遍歷薄啥,在沒(méi)有 JDK 并未提供迭代器時(shí)辕羽,我們對(duì)于數(shù)據(jù)的遍歷處理如下:
- 對(duì)于數(shù)組的遍歷處理:
Bean[] beans = new Bean[5];
for (int i = 0; i < beans.length; i++) {
beans[i] = new Bean();
// todo something
}
- 對(duì) ArrayList 的遍歷處理:
ArrayList<Bean> beanArrayList = new ArrayList<Bean>();
for (int i = 0; i < beanArrayList.size(); i++) {
beanArrayList.add(new Bean());
// todo something
}
可以看出,如果我們想對(duì)一個(gè)空的 Java 集合添加數(shù)據(jù)垄惧,那我們就必須知道該集合內(nèi)部的數(shù)據(jù)結(jié)構(gòu)(即刁愿,以數(shù)組和 ArrayList 為例,添加時(shí)的操作應(yīng)該是beans[i] = new Bean();
還是beanArrayList.add(new Bean());
)到逊,這樣就導(dǎo)致了訪(fǎng)問(wèn)邏輯與集合的結(jié)構(gòu)本身緊密耦合(即铣口,每一種不同的數(shù)據(jù)集合對(duì)應(yīng)了不同的便利方法),這會(huì)使得代碼無(wú)法復(fù)用觉壶。
而 Iterator
可以輕松的解決上述問(wèn)題.
java.util.Iterator
看一下官方未出的解釋?zhuān)?/p>
public interface Iterator<E>
An iterator over a collection.Iterator
takes the place ofEnumeration
in the Java Collections Framework. Iterators differ from enumerations in two ways:
- Iterators allow the caller to remove elements from the underlying collection during the iteration with well-defined semantics.
- Method names have been improved.
This interface is a member of the Java Collections Framework
就是說(shuō)脑题,Iterator
是一個(gè)對(duì) collection 集合進(jìn)行迭代的迭代器(接口)。Iterator
迭代器取代了 Java Collections Framework 中的 Enumeration
铜靶。該接口是 Java Collections Framework 的成員叔遂。迭代器與枚舉有兩點(diǎn)不同:
- 迭代器允許調(diào)用者利用定義良好的語(yǔ)義在迭代期間從迭代器所指向的 collection 移除元素。
- 方法名稱(chēng)得到了改進(jìn)争剿。
.
這也就意味著已艰,Iterator
使用相同的訪(fǎng)問(wèn)邏輯完成集合的遍歷,使得我們?cè)谠L(fǎng)問(wèn)集合元素時(shí),無(wú)需關(guān)心不同的集合內(nèi)部結(jié)構(gòu)蚕苇。從而降低訪(fǎng)問(wèn)邏輯與集合本身的耦合度哩掺。
Iterator
接口源代碼如下:
package java.util;
import java.util.function.Consumer;
public interface Iterator<E> {
// 返回迭代是否有更多的元素。
boolean hasNext();
// 返回迭代器剛越過(guò)的元素的引用
E next();
// 從底層集合中移除此迭代器返回的最后一個(gè)元素(可選操作)
default void remove() {
throw new UnsupportedOperationException("remove");
}
// 對(duì)每個(gè)剩余的元素執(zhí)行給定的操作涩笤,直到處理完所有元素或操作拋出異常
default void forEachRemaining(Consumer<? super E> action) {
Objects.requireNonNull(action);
while (hasNext())
action.accept(next());
}
}
如何使用 Iterator
在使用中嚼吞,我們既可以借助hasNext()
及next()
方法盒件,對(duì)已知集合結(jié)構(gòu)的集合對(duì)象完成簡(jiǎn)單的迭代(類(lèi)似于之前的方案),就像這樣:
Iterator<Bean> beanIterator = beanArrayList.iterator();
while (beanIterator.hasNext()) {
Bean bean = beanIterator.next();
// todo something
}
更新于2017.12.03
僅僅這樣不是與之前的方案沒(méi)什么區(qū)別了嗎誊薄?當(dāng)然履恩,它能做的還可以更多。做到真正不去關(guān)心集合內(nèi)部結(jié)構(gòu)的迭代手段呢蔫,下述代碼是對(duì)一個(gè)集合對(duì)象的迭代:
public static boolean isExist(Collection<Bean> beans, Bean bean) {
Iterator<Bean> iterator = beans.iterator();
System.out.println(beans.getClass().getSimpleName() + ":");
while (iterator.hasNext()) {
if (iterator.next().equals(bean)) {
System.out.println("集合中已存在 Bean[" + bean + "]");
return true;
}
}
return false;
}
Test:
public static final void main(String[] args) {
Bean bean0 = new Bean().setId("01");
Bean bean1 = new Bean().setId("02");
ArrayList<Bean> beanArrayList = new ArrayList<>();
Queue<Bean> beanQueue = new LinkedBlockingQueue<>();
HashMap<Bean, Bean> map = new HashMap<>();
beanArrayList.add(bean0);
beanArrayList.add(bean1);
map.put(bean0, bean0);
map.put(bean1, bean1);
beanQueue.add(bean0);
beanQueue.add(bean1);
isExist(map.keySet(), bean0);
isExist(beanArrayList, bean1);
isExist(beanQueue, bean1);
}
輸出結(jié)果:
KeySet:
集合中已存在 Bean[Bean{id='01', password='null'}]
ArrayList:
集合中已存在 Bean[Bean{id='02', password='null'}]
LinkedBlockingQueue:
集合中已存在 Bean[Bean{id='02', password='null'}]
總結(jié)
所有Collection框架中的j幾乎所有的集合類(lèi)(或接口)(如ArrayList切心、Set、Queue等)都實(shí)現(xiàn)了(接口也聲明了iterator()
方法)自己的內(nèi)部的迭代器片吊,但無(wú)疑都是Iterator
的實(shí)現(xiàn)绽昏。
不過(guò)據(jù)我現(xiàn)在所了解到的,數(shù)組由于其本身的實(shí)現(xiàn)方案與 "編譯處理和
JVM 的native()
方法有關(guān)俏脊,似乎不能直接獲取到其本身的迭代器全谤。如果有哪位朋友知道相關(guān)方法,請(qǐng)?jiān)u論告知爷贫,不勝感謝认然。
這是第一次嘗試寫(xiě)學(xué)習(xí)筆記,希望以后可以堅(jiān)持下去漫萄,事無(wú)巨細(xì)地卷员,從點(diǎn)滴累積自己的財(cái)富。