集合的迭代器 任何集合都有迭代器。 任何集合類,都必須能以某種方式存取元素,否則這個集合容器就沒有任何意義。 迭代器,也是一種模式(也叫迭代器模式)。在java中它是一個對象,其目的是遍歷並選中其中的每個元素,而使用者(客戶端)無需知道裡面的具體細節。迭代器要足夠的“輕量”——創建迭代器的代價小。所 ...
集合的迭代器
任何集合都有迭代器。
任何集合類,都必須能以某種方式存取元素,否則這個集合容器就沒有任何意義。
迭代器,也是一種模式(也叫迭代器模式)。在java中它是一個對象,其目的是遍歷並選中其中的每個元素,而使用者(客戶端)無需知道裡面的具體細節。迭代器要足夠的“輕量”——創建迭代器的代價小。所以看迭代器的源代碼就會發現,裡面會有很多要求:
- iterator方法返回一個Iterator,Iterator返回序列的頭元素。
- next方法獲取下一個元素
- hasNext檢查還有元素
- remove刪除迭代器新返回的元素
下麵是迭代器的基本使用
public class UsingIterator {
public static void main(String[] args) {
List<String> names = Arrays.asList("marson", "shine", "summer", "zhu");
Iterator<String> it = names.iterator();
while(it.hasNext()){
String s = it.next();
print(s);
}
for (String s : names){
print(s);
}
System.out.println();
it = names.iterator();
for (int i = 0; i < 4; i++) {
it.next();
}
print(names);
}
}
ListIterator
ListIterator是一個更強大的Iterator子類型,能用於各種List類訪問,前面說過Iterator支持單向取數據,ListIterator可以雙向移動,所以能指出迭代器當前位置的前一個和後一個索引,可以用set方法替換它訪問過的最後一個元素。我們可以通過調用listIterator方法產生一個指向List開始處的ListIterator,並且還可以用過重載方法listIterator(n)來創建一個指定列表索引為n的元素的ListIterator。
public class ListIteration {
public static void main(String[] args) {
var names = Arrays.asList("marson", "shine", "summer", "zhu");
var it = names.listIterator();
while (it.hasNext()) {
print(it.next() + ", " + it.nextIndex() + ", " + it.previousIndex() + "; ");
}
while (it.hasPrevious()) {
print(it.previous() + " ");
}
print(names);
it = names.listIterator(3);
while (it.hasNext()) {
it.next();
it.set("alias");
}
print(names);
}
}
輸出結果為:
marson, 1, 0;
shine, 2, 1;
summer, 3, 2;
zhu, 4, 3;
zhu
summer
shine
marson
[marson, shine, summer, zhu][marson, shine, summer, alias]
Iterator模式
前面說了,迭代器又叫迭代器模式,顧名思義,只要符合這種模式都能叫迭代器模式,自然也能像前面一樣使用迭代器
那麼Iterator模式具體是個什麼樣子的模式呢?
我們通過Collection的源碼發現其中的樣子(為什麼要看Collection而不是其他的List?因為Collection是所有容器的基類啊)
通過Collection代碼我們發現它繼承了一個叫Iterable<T>
介面,註解說的很清楚——實現這個介面就說明這個對象是可迭代的;並且其成員函數也很清晰,只有三個方法
public interface Iterable<T> {
Iterator<T> iterator();
default void forEach(Consumer<? super T> action); //省略部分代碼
default Spliterator<T> spliterator(); //省略部分代碼
}
public interface Iterator<E> {
boolean hasNext();
E next();
default void remove() {
throw new UnsupportedOperationException("remove");
}
...
}
Iterator這個泛型介面才是我們真正實現迭代的核心,通過這些信息我們嘗試來寫一個迭代器
public class CustomIterator implements Iterable<String> {
protected String[] names = ("marson shine summer zhu").split(" ");
public Iterator<String> iterator() {
return new Iterator<String>() {
private int index = 0;
@Override
public boolean hasNext() {
return index < names.length;
}
@Override
public String next() {
return names[index++];
}
public void remove() {
}
};
}
public static void main(String[] agrs) {
for (var s : new CustomIterator()) {
print(s + " ");
}
}
}
到這裡,自定義的迭代器就寫完了,實際上我們只需要繼承一個Iterable介面然後實現這個介面就行了,更深入的話,其實還可以自己寫一個listIterator實現雙向的操作數據