《JAVA API-集合》2 Iterator

1 Iterator接口提供了4個方法:hasNext、next、remove、forEachRemaining

2 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
        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();
            }
        }

        @Override
        @SuppressWarnings("unchecked")
        public void forEachRemaining(Consumer<? super E> consumer) {
            Objects.requireNonNull(consumer);
            final int size = ArrayList.this.size;
            int i = cursor;
            if (i >= size) {
                return;
            }
            final Object[] elementData = ArrayList.this.elementData;
            if (i >= elementData.length) {
                throw new ConcurrentModificationException();
            }
            while (i != size && modCount == expectedModCount) {
                consumer.accept((E) elementData[i++]);
            }
            // update once at end of iteration to reduce heap write traffic
            cursor = i;
            lastRet = i - 1;
            checkForComodification();
        }

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

 

(1)remove()和lastRet

remove()中刪除的是下標爲lastRet的元素,並且lastRet設置爲-1;lastRet只有在初始化和remove()後爲-1,其餘時候lastRet = cursor - 1。

如果沒有調用任何方法直接調用remove()會報錯,所以Iterator的設計思路是:刪除是刪除上一個返回的元素

(2)在遍歷的時候刪除,有三種遍歷方式

List<String> list = new ArrayList<String>();
		for (int i = 0;i < 10;i++) {
			list.add( Integer.toString(i));
		}
		
		for (String item : list) {
			if ("0".equals(item)) {
				list.remove("0");
			}
		}
		
		for (int i = 0;i < list.size();i++) {
			if ("0".equals(list.get(i))) {
				list.remove(i);
			}
		}
		
		Iterator<String> iter = list.iterator();
		while (iter.hasNext()) {
			if ("0".equals(iter.next())) {
				iter.remove();
			}
		}
  • 增強for循環:通過彙編代碼或者直接debug發現實際上用的是Iterator接口實現。如果在增強for循環中用list的remove方法會報ConcurrentModificationException,也就是觸發了fail-fast機制,ArrayList中的fail-fast是通過checkForComodification方法實現的。根據官方的解釋:fail-fast機制僅用於檢測bug。
  • 普通for循環:不會報錯,但是由於刪除了元素,數組的下標會改變,導致元素的獲取會出現問題。
  • Iterator遍歷:必須先調用next()方法然後再刪除
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章