1.iterator遍歷linkedlist集合
Iterator li = list.iterator(); while(li.hasNext()){ System.out.println(li.next()); }
這里可以看見Iterator li = list.iterator();
public Iterator<E> iterator() { return new Itr(); }
那么這個iterator()方法是在它的抽象父類中,通過new Itr();去實例化這個Iterator對象。
public boolean hasNext() { return cursor != size(); }
這里cursor初始化值為0;
當cursor等於size的時候,hasNext返回false;
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(); } }
那么這里可以一個很關鍵的一點它使用的還是get方法。
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; } }
那我們現在看看get()方法是怎么遍歷Node的無論無論這個index是多少?它都從first開始,或者last,取決於index < (size >> 1),這是個很巧妙的設計。看看index是不是超過size的一般,選擇從后first還是last,這時我們也可以找到鏈表結構查詢慢的根本原因,在於無論這個size有多大它都需要從first后last開始查詢。遠遠慢於使用索引的arraylist。
2.iterator遍歷ArrayList集合
public E get(int index) { rangeCheck(index); return elementData(index); }
事實上iterator();是在Arraylist和linkedlist的共同抽象父類abstractList中,唯有get();實現不同,所以Arraylist查詢的速度要遠遠高於LinkedList.
2.iterator遍歷hushmap集合
add(); Iterator<String> map = map.keySet().iterator(); while(map.hasNext()){ System.out.println(map.next()); }
那么這里就是遍歷key一種方法,map.keySet().iterator();下面來看keyset()方法
public Set<K> keySet() { Set<K> ks; return (ks = keySet) == null ? (keySet = new KeySet()) : ks; }
這里是通過keysett對象這里來看keySet類的iterator()方法
public final Iterator<K> iterator() { return new KeyIterator(); }
這里就通過KeyIterator()方法實現了這個Iterator接口,這時候我們看KeyIterator()是如何重寫這個next()方法的。
public final K next() { return nextNode().key; } }
那么這里返回nextNode().key;現在來看nextNode()
final Node<K,V> nextNode() { Node<K,V>[] t; Node<K,V> e = next; if (modCount != expectedModCount) throw new ConcurrentModificationException(); if (e == null) throw new NoSuchElementException(); if ((next = (current = e).next) == null && (t = table) != null) { do {} while (index < t.length && (next = t[index++]) == null); } return e; }
這里就是遍歷的核心內容,因為hashtable的關系,它的遍歷需要判斷table數組的鏈表中是否沒有數據,如果沒有數據而且table還沒有到最大值,這時候我們的table數組下標加以1,開始遍歷下一個數組,因為我們put一個對象時,它的存儲方式完全根據對象的hashcode來存儲的,本身它的取值是有順序的,但是存儲的時候是無序,所以取出來的數據也就沒有順序可言了。
map.values.iterator();
這里就很簡單了,nextnode.key變成nextnode.value;
網上有人說遍歷key和value的性能不一樣,不知道為什么,看到這里,我認為性能是沒有區別的。
關於hashSet的遍歷
參照map.keyset().iterator();