JAVA集合:迭代器實現原理
阿新 • • 發佈:2018-12-15
前言
在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();
}
}
其他的都差不多,就不貼原始碼了,理解原理最重要。