1. 程式人生 > >ArrayList的迭代器和 超強for迴圈

ArrayList的迭代器和 超強for迴圈

超強for迴圈 也是用迭代器實現的。

有個面試官,問去除ArrayList的一些元素,當時寫的是for迴圈,判斷去除,然後左邊退一位。他說不安全。

用迭代器遍歷安全,迭代器包含一個remove方法,去除元素後自帶遊標退一位。

主要三個方法,hasnext,next,和remove

   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
        int expectedModCount = modCount;

        public boolean hasNext() {
            return cursor != size;
        }

        @SuppressWarnings("unchecked")
        public E next() {
            checkForComodification();
            int i = cursor;
            if (i >= size)
                throw new NoSuchElementException();
            Object[] elementData = ArrayList.this.elementData;
            if (i >= elementData.length)
                throw new ConcurrentModificationException();
            cursor = i + 1;
            return (E) elementData[lastRet = i];
        }

        public void remove() {
            if (lastRet < 0)
                throw new IllegalStateException();
            checkForComodification();

            try {
                ArrayList.this.remove(lastRet);
                cursor = lastRet;
                lastRet = -1;
                expectedModCount = modCount;
            } catch (IndexOutOfBoundsException ex) {
                throw new ConcurrentModificationException();
            }
        }

轉載:https://blog.csdn.net/H_Gao/article/details/52901297

package com.wind.gaohui;
import java.util.ArrayList;
import java.util.List;
public class TestFor {
    public static void main(String[] args) {
        List<String> lists = new ArrayList<String>();
        if(lists.size()>0) {
            for
(String str : lists) { System.out.println(str.toString()); } } } }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

首先,來看上面一段程式碼片段,對於一個空的集合,使用增強for迴圈遍歷的時候,我們是不是需要對集合的size進行判斷以防止出現空指標的異常呢?

之前一直以為這是必須的,直到最近親手測試了下,發現對集合的size判斷完全是沒有必要的。

其實,增強for迴圈的內部其實就是用Iterator來實現的。

那麼何以見得呢?

package com.wind.gaohui;
import
java.util.ArrayList; import java.util.List; public class TestFor { public static void main(String[] args) { List<String> lists = new ArrayList<String>(); for(String str : lists) { System.out.println(str.toString()); } } }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

針對上面這行程式碼,我們使用javap來檢視編譯生成的位元組碼如下圖: 
-c引數表示對這段程式碼進行反編譯。

image

package com.wind.gaohui;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class TestIterator {
    public void testIterator() {
        List<String> lists = new ArrayList<String>();
        Iterator<String> strs = lists.iterator();
        while(strs.hasNext()){
            System.out.println(strs.next());
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

接著我們用Iterator的方式遍歷這個空的結合,再用javap工具對這段Iterator的程式碼進行反編譯, 
得到如下的結果: 
image

我們發現增強for迴圈遍歷和iterator遍歷反編譯後的位元組碼完全一樣,這樣,我們就大概明白了增強for迴圈實際上內部就是iterator。

由於使用iterator機制,所以在遍歷的時候根本不需要進行size大小的判斷,因為iterator機制中就進行了判斷,strs.hasNext(),當這個遊標最開始在集合最前面的時候,就會判斷下一個位置是否有元素