java集合原始碼分析(二)---ListIterator與Iterator
吐槽
早上起來刷牙洗臉洗頭髮後,正準備去上課,然後發現今天早上好像不上課emmmmmm,然後就早上繼續看下java集合方面的原始碼了吼吼吼
Iterator
上次好像說過一點這個,然後繼續複習下這個
還是先看下官方文件 然後我們發現這個東西就是個功能很少但很實用的迭代器,但是它也要注意一下幾點:
- 使用方法iterator()要求容器返回一個Iterator。第一次呼叫Iterator的next()方法時,它返回序列的第一個元素
- 它只能單向移動
- 使用next()獲得序列中的下一個元素。
- 使用hasNext()檢查序列中是否還有元素
- 使用remove()將迭代器新返回的元素刪除
Iterator 的使用
所有 Collection 的子類都有 iterator() 方法來獲得 Iterator,通過 Iterator 的標準操作方法,可以讓我們不必關心具體集合的型別,從而避免向客戶端暴露出集合的內部結構。
這個我們之前看過Collection 介面的原始碼裡面就有返回一個 Iterator的方法
具體的操作也是很簡單的 先建立一個集合上面的迭代器物件 然後判定是否有下一個 有就返回當前指向的元素//第一次next()是第一個元素
Iterator iterator = list.iterator();
while (iterator.hasNext()){
System. out.println(iterator.next());
}
如果我們不用這個的話,那就for迴圈遍歷唄
for(int i=0; i<集合的大小;i++){
// ...
}
這兩種遍歷的區別就是, Iterator體集合型別耦合性弱,複用性更強。缺點就是無法獲取指定的元素,只能挨個遍歷。
而且具體的集合用的時候,它們會實現裡面的方法的
ListIterator
這個還是個介面,繼承於Iterator,比Iterator更加功能強大一點 還是先看下官方的文件 我們發現這個加強版的迭代器比之前多了很多的方法
- 現在可以前後兩個方向遍歷List了
- 在遍歷的時候可以修改List的元素
- 遍歷的時候獲取迭代器的當前的遊標的位置
這塊遊標的是個很神奇的東西,看下文件上面的解釋 這裡的游標位置就是我們說的遊標 在n個元素的列表裡面,遊標的位置在兩個元素的中間,一共有n+1個遊標的位置 看下我畫的3個圖
圖一:初始情況 //初始時它在第 0 個元素之前 圖二:當呼叫next()之後,遊標向後移動一個位置 圖三:當遍歷完所有的元素的時候
看完這三個圖就知道為啥n個元素可以放n+1個位置了emmmm
然後再看下它新加的幾個方法
- void hasPrevious() 判斷遊標前面是否有元素;
- Object previous() 返回遊標前面的元素,同時遊標前移一位
- int nextIndex() 返回遊標後邊元素的索引位置,初始為 0 ;遍歷 N 個元素結束時為 N
- int previousIndex() 返回遊標前面元素的位置,初始時為 -1
- void add(E) 在遊標 前面 插入一個元素
- void set(E) 更新迭代器最後一次操作的元素為 E,也就是更新最後一次呼叫 next() 或者 previous() 返回的元素
- void remove() 刪除迭代器最後一次操作的元素,注意事項和 set 一樣。
然後我想看下這個介面的具體的實現,然後找啊找,發現了一個抽象類AbstractIndexedListIterator 它先它繼承於UnmodifiableListIterator類,我們進去看下
public abstract class UnmodifiableListIterator<E> extends UnmodifiableIterator<E> implements ListIterator<E> {
protected UnmodifiableListIterator() {
}
/** @deprecated */
@Deprecated
public final void add(E var1) {
throw new UnsupportedOperationException();
}
/** @deprecated */
@Deprecated
public final void set(E var1) {
throw new UnsupportedOperationException();
}
}
進去看了下,這個類就繼承一個類,然後實現了ListIterator介面 我們還是退回去看下AbstractIndexedListIterator的原始碼
abstract class AbstractIndexedListIterator<E> extends UnmodifiableListIterator<E> {
private final int size;//元素的個數
private int position;//下標的位置
protected abstract E get(int var1);
protected AbstractIndexedListIterator(int var1, int var2) {
Preconditions.checkPositionIndex(var2, var1);
this.size = var1;
this.position = var2;
}
public final boolean hasNext() {
return this.position < this.size;//每次都判斷下游標和元素總的個數比較
}
public final E next() {
if (!this.hasNext()) {
throw new NoSuchElementException();
} else {
return this.get(this.position++);//遊標加一,往後移一個位置
}
}
public final int nextIndex() {
return this.position;//返回遊標後邊元素的索引位置,初始為 0
}
public final boolean hasPrevious() {
return this.position > 0;//因為遊標的初始值是-1,所以判斷遊標前面是否有元素;
}
public final E previous() {
if (!this.hasPrevious()) {
throw new NoSuchElementException();
} else {
return this.get(--this.position);//返回遊標前面的元素,同時遊標前移一位
}
}
public final int previousIndex() {
return this.position - 1;//返回遊標前面元素的位置,初始時為 -1
}
}
但是好像因為List 的子類 ArrayList, LinkedList, Vector 由於底層實現原理不同(陣列,雙向連結串列),具體操作類實現有所不同。 所以,到時候問題具體分析吧