1. 程式人生 > >JAVA集合:迭代器實現原理

JAVA集合:迭代器實現原理

前言

在JAVA的學習和開發中,經常需要對集合或者陣列進行遍歷,遍歷的方法有多種:for迴圈、foreach、迭代器。
for迴圈的實現簡單明瞭,就是迴圈下標,判斷邊界,取到每個下標的資料。至於foreach和迭代器,其實foreach在反編譯以後可以看到就是迭代器實現的,因此,今天來學習一下迭代器的實現原理。

Iterable 與 Iterator

Iterable:

//Iterable用來標識可以迭代
public interface Iterable<T> {
	//只有一個返回迭代器的方法
    Iterator<T> iterator();
}

//集合的父介面Collection繼承自Iterable,所以List和Set都有返回迭代去的方法
public interface Collection<E> extends Iterable<E> {
}

Iterator:
迭代器介面

public interface Iterator<E> {
   //判斷邊界,是否還有下一個物件,即是否還能迭代
    boolean hasNext();
   //返回下一個物件
    E next();
   //移除當前指標指向的物件
    void remove();
}

迭代器的使用流程是:
1、通過hasNext判斷邊界,是否可以繼續迭代
2、通過next() 方法返回指標指向的物件
3、remove()方法移除指標指向的物件,remove之前必須先執行過next()

迭代器在不同的集合裡有不同的實現。
下面來看下各種集合的迭代器實現,主要理解原理。

ArrayList

//迭代器
private class Itr implements Iterator<E> {
//遊標
       int cursor = 0;
       
        int lastRet = -1;
	//記錄修改次數,每次修改+1
        int expectedModCount = modCount;
	
	//是否還有下一條資料,只需判斷遊標是否不等於size() ,
        public boolean hasNext() {
            return cursor != size();
        }
	
	//取到這個遊標的資料
        public E next() {
            checkForComodification();
            try {
                int i = cursor;
                E next = get(i);
                lastRet = i;
                cursor = i + 1;
                return next;
            } catch (IndexOutOfBoundsException e) {
                checkForComodification();
                throw new NoSuchElementException();
            }
        }
	
	//在迭代器中移除
        public void remove() {
        //一次迭代 不能remove多次
            if (lastRet < 0)
                throw new IllegalStateException();
            checkForComodification();

            try {
                AbstractList.this.remove(lastRet);
                if (lastRet < cursor)
                    cursor--;
                lastRet = -1;
                //更新expectedModCount為最新
                expectedModCount = modCount;
            } catch (IndexOutOfBoundsException e) {
                throw new ConcurrentModificationException();
            }
        }
	
	//在迭代器之外修改資料就會報錯
        final void checkForComodification() {
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
        }
    }

//實現從後往前遍歷
private class ListItr extends Itr implements ListIterator<E> {
        ListItr(int index) {
            cursor = index;
        }

        public boolean hasPrevious() {
            return cursor != 0;
        }

        public E previous() {
            checkForComodification();
            try {
                int i = cursor - 1;
                E previous = get(i);
                lastRet = cursor = i;
                return previous;
            } catch (IndexOutOfBoundsException e) {
                checkForComodification();
                throw new NoSuchElementException();
            }
        }

        public int nextIndex() {
            return cursor;
        }

        public int previousIndex() {
            return cursor-1;
        }

        public void set(E e) {
            if (lastRet < 0)
                throw new IllegalStateException();
            checkForComodification();

            try {
                AbstractList.this.set(lastRet, e);
                expectedModCount = modCount;
            } catch (IndexOutOfBoundsException ex) {
                throw new ConcurrentModificationException();
            }
        }

        public void add(E e) {
            checkForComodification();

            try {
                int i = cursor;
                AbstractList.this.add(i, e);
                lastRet = -1;
                cursor = i + 1;
                expectedModCount = modCount;
            } catch (IndexOutOfBoundsException ex) {
                throw new ConcurrentModificationException();
            }
        }
    }

LinkedList

 private class ListItr implements ListIterator<E> {
        private Node<E> lastReturned = null;
        private Node<E> next;
        private int nextIndex;
        private int expectedModCount = modCount;

        ListItr(int index) {
            // assert isPositionIndex(index);
            next = (index == size) ? null : node(index);
            nextIndex = index;
        }
	//判斷下一個index<size說明有下一條
        public boolean hasNext() {
            return nextIndex < size;
        }

        public E next() {
            checkForComodification();
            if (!hasNext())
                throw new NoSuchElementException();
	    
            lastReturned = next;
            next = next.next;
            //索引+1
            nextIndex++;
            //返回資料
            return lastReturned.item;
        }

        public boolean hasPrevious() {
            return nextIndex > 0;
        }

        public E previous() {
            checkForComodification();
            if (!hasPrevious())
                throw new NoSuchElementException();

            lastReturned = next = (next == null) ? last : next.prev;
            nextIndex--;
            return lastReturned.item;
        }

        public int nextIndex() {
            return nextIndex;
        }

        public int previousIndex() {
            return nextIndex - 1;
        }

        public void remove() {
            checkForComodification();
            if (lastReturned == null)
                throw new IllegalStateException();

            Node<E> lastNext = lastReturned.next;
            unlink(lastReturned);
            if (next == lastReturned)
                next = lastNext;
            else
                nextIndex--;
            lastReturned = null;
            expectedModCount++;
        }

        public void set(E e) {
            if (lastReturned == null)
                throw new IllegalStateException();
            checkForComodification();
            lastReturned.item = e;
        }

        public void add(E e) {
            checkForComodification();
            lastReturned = null;
            if (next == null)
                linkLast(e);
            else
                linkBefore(e, next);
            nextIndex++;
            expectedModCount++;
        }

        final void checkForComodification() {
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
        }
    }

其他的都差不多,就不貼原始碼了,理解原理最重要。