有位小朋友最近正在爲年後換工做作準備,可是遇到一個問題,以爲很難以想象的一道筆試題。而後我把這道題發到技術羣裏,發現不少人竟然不知道,不少都是連蒙帶猜的說。感受頗有必要寫一篇文章來講道說道。java
閱讀下面這段代碼,請寫出這段代碼的輸出內容:面試
import java.util.ArrayList;import java.util.Iterator;import java.util.*;public class Test { public static void main(String[] args) { List<String> list = new ArrayList<>(); list.add("1"); list.add("2"); list.add("3"); Iterator iterator = list.iterator(); while (iterator.hasNext()) { String str = (String) iterator.next(); if (str.equals("2")) { iterator.remove(); } } while (iterator.hasNext()) { System.out.println(iterator.next()); } System.out.println("4"); }}
他寫出來的答案是:算法
134
奇怪的是,你把這道題目發給你身邊人,讓他們回答這道面試題輸出結果是什麼,說這個結果的人很是多。不行你試試設計模式
~數組
答案明顯不對,由於在第一個while裏的 iterator.hasNext()==false後纔會到第二個while裏來,同一個Iterator對象,前面調一次iterator.hasNext()==false,再判斷一次結果不仍是同樣嗎?,數據結構
因此第二個while判斷爲false,也就不會再去遍歷iterator了,由此可知本體答案是:4。app
下面咱們來分析一下爲何是具體底層是怎麼實現的。ide
public interface Iterator<E> { //每次next以前,先調用此方法探測是否迭代到終點 boolean hasNext(); //返回當前迭代元素 ,同時,迭代遊標後移 E next(); /*刪除最近一次已近迭代出出去的那個元素。 只有當next執行完後,才能調用remove函數。 好比你要刪除第一個元素,不能直接調用 remove() 而要先next一下( ); 在沒有先調用next 就調用remove方法是會拋出異常的。 這個和MySQL中的ResultSet很相似 */ default void remove() { throw new UnsupportedOperationException("remove"); } default void forEachRemaining(Consumer<? super E> action) { Objects.requireNonNull(action); while (hasNext()) action.accept(next()); }}
這裏的實現類是ArrayList的內部類Itr。函數
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 //modCountshi ArrayList中的屬性,當添加或刪除的時候moCount值會增長或者減小 //這裏主要是給fail-fast使用,避免一遍在遍歷,一遍正在修改致使數據出錯 //此列表在結構上被修改的次數。結構修改是指改變結構尺寸的修改列表, //或者以這樣的方式對其進行擾動,進步可能會產生錯誤的結果。 int expectedModCount = modCount; public boolean hasNext() { //cursor初始值爲0,沒掉一次next方法就+1 //size是ArrayList的大小 return cursor != size; } @SuppressWarnings("unchecked") public E next() { checkForComodification(); int i = cursor; if (i >= size) throw new NoSuchElementException(); //把ArrayList中的數組賦給elementData Object[] elementData = ArrayList.this.elementData; if (i >= elementData.length) throw new ConcurrentModificationException(); //每調用一次next方法,遊標就加1 //cursor=lastRet+1 cursor = i + 1; //返回ArrayList中的元素 return (E) elementData[lastRet = i]; } public void remove() { if (lastRet < 0) throw new IllegalStateException(); checkForComodification(); try { //調用ArrayList中remove方法,溢出該元素 ArrayList.this.remove(lastRet); //cursor=lastRet+1, //因此此時至關於cursor=cursor-1 cursor = lastRet; lastRet = -1; expectedModCount = modCount; } catch (IndexOutOfBoundsException ex) { throw new ConcurrentModificationException(); } } final void checkForComodification() { if (modCount != expectedModCount) throw new ConcurrentModificationException(); }}
再回到上面題目中:ui
第1次循環
第2次循環
第3次循環
第4次循環
hasNext方法中:cursor==2, size==2,因此cursor != size返回false。
因此,最後只輸出"4",即答案爲4.