一、Iterator的API
關於Iterator主要有三個方法:hasNext()、next()、remove()
hasNext:沒有指針下移操作,只是判斷是否存在下一個元素
next:指針下移,返回該指針所指向的元素
remove:刪除當前指針所指向的元素,一般和next方法一起用,這時候的作用就是刪除next方法返回的元素
二、Iterator原理
迭代器是將集合的數據放到一個容器中並排成一排,iterator有一個遊標,最初的時候,遊標在第一個元素前面,調用Iterator.next()是將遊標往後移一位,Iterator.hasNext()是判斷遊標後面還沒有可以迭代的元素。
三、爲什麼用迭代器?
因爲最初的時候你用for循環遍歷List,之後人家又要你遍歷Set,但是for循環無法遍歷Set,因爲Set是無序的(無法get值),所以後面就統一用迭代器遍歷集合了。
四、迭代器爲什麼不定義成一個類,而是一個接口?
假如迭代器是一個類,我們就可以創建該類的對象,然後調用該類的方法來遍歷集合。
但是,Java定義了很多的集合類,他們的數據結構不相同,所以他們存儲的方式和遍歷的方法也應該是不相同的。所以最終就沒有定義迭代器類。
而無論你是哪種集合,你都應該具備獲取元素的操作。並且,最好輔助於判斷功能,這樣先判斷再獲取,就不會出錯。也就是說,判斷和獲取功能應該是集合所具備的,而因爲不同集合的數據結構不一樣,所以他們的判斷方式也不一樣。我們把這兩種功能抽象出來爲,不提供具體實現,就是接口。
五、如何實現迭代器?
在真正的具體類中,以內部類的方式體現出來。
每個集合類內部都含有一個內部類,用來實現Iterator接口。集合類的iterator方法就是在獲取內部類對象(迭代器對象),然後通過該對象調用hashNext和next方法實現遍歷。-
class ArrayList{
public Iterator<E> iterator(){return new Itr();}
class Itr implements Iterator{
public hasNext(){……}//重寫這兩個方法,實現元素遍歷
public next(){……}
}
}
通過內部類,我們纔可以使用諸如list.iterator().hasNext()這樣的方法。
六、迭代器迭代順序
HashMap按鍵的順序,HashSet按hashCode的順序。
七、爲什麼被迭代的對象不允許被改變?
用迭代器本身刪除是可以的,但是在迭代器中對集合本身進行刪除就不行了, 對於這種莫名其妙的問題,我們從源碼入手
我們注意到expectedModCount這個字段,他的初始值是等於modCount的。 而當我們不通過迭代器對集合進行增刪時,modCount的值會發生改變,最後拋出異常
那麼爲什麼要這樣呢?
迭代器是工作在一個獨立的線程中,並且擁有一個mutex鎖,就是說iterator在工作的時候,是不允許被迭代的對象被改變的。(至於爲什麼不允許改變)
iterator被創建的時候建立一個內存索引表(單鏈表),這個索引表指向原來的對象,當原來的對象數量改變的時候,這個索引表的內容沒有同步改變,所以當索引指針往下移的時候,便找不到要迭代的對象,於是錯誤。
List、Set等是動態的,可變對象的數量的數據結構,但是iterator則是單向不可變的,只能順序讀取,不能逆序操作的數據結構,當iterator指向的原始數據發生變化時,iterator自己就迷失了方向。
注:正是因爲這個原因,一定要注意線程安全問題。
參考博客:
https://blog.csdn.net/liyancheng984807972/article/details/9744949
https://blog.csdn.net/hellowordapi/article/details/54233590
https://blog.csdn.net/xiakexiaohu/article/details/73017210
https://blog.csdn.net/shuaishuai3409/article/details/52210255