Java fori和foreach的效能差別
阿新 • • 發佈:2019-02-20
概述
fori和foreach的根本區別在於
- fori是通過下標訪問
- foreach是通過容器的itrator的next()方法來迭代
ArrayList:fori效能高於foreach
因為使用fori,是通過下標訪問:
public E get(int index) {
if (index < 0 || index >= this.size)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
if (ArrayList.this.modCount != this.modCount)
throw new ConcurrentModificationException();
return (E) ArrayList.this.elementData[offset + index];
}
而使用foreach,是通過iterator的next方法:
public E next() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
int i = cursor;
if (i >= limit)
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length)
throw new ConcurrentModificationException();
cursor = i + 1;
return (E) elementData[lastRet = i];
}
我們可以看到,對於ArrayList來說,foreach需要做同步檢查,所以必然比fori要慢。
LinkedList:fori效能低於foreach
fori,通過下標:
public E get(int index) {
checkElementIndex(index);
return node(index).item;
}
//LinkedList是一個雙向連結串列,只需迭代一半
Node<E> node(int index) {
// assert isElementIndex(index);
if (index < (size >> 1)) {
Node<E> x = first;
for (int i = 0; i < index; i++)
x = x.next;
return x;
} else {
Node<E> x = last;
for (int i = size - 1; i > index; i--)
x = x.prev;
return x;
}
}
foreach,通過迭代器:
public E next() {
checkForComodification();
if (!hasNext())
throw new NoSuchElementException();
lastReturned = next;
next = next.next;
nextIndex++;
return lastReturned.item;
}
對於LinkedList,通過下標的話每次都要迭代一半的長度,而通過迭代器,每次迭代只需要移動一下指標。顯然foreach效能要高於fori