LinkedList
1. 切记一定不要使用普通for循环去遍历LinkedList。使用迭代器或者foreach循环
原因:for循环时获取每个节点的时候都调用到了LinkedList的get()方法,从以下代码的20行~29行可以看出每一次获得一个节点的值都是从头开始for下去,当LinkedList里面的元素越来越多,则花费的时间就成倍增加,LinikedList遍历的时间复杂度为O(N 2 )
1 /** 2 * Returns the element at the specified position in this list. 3 * 4 * @param index index of the element to return 5 * @return the element at the specified position in this list 6 * @throws IndexOutOfBoundsException { @ inheritDoc } 7 */ 8 public E get( int index) { 9 checkElementIndex(index); 10 return node(index).item; 11 } 12 13 14 /** 15 * Returns the (non-null) Node at the specified element index. 16 */ 17 Node<E> node( int index) { 18 // assert isElementIndex(index); 19 20 if (index < ( size >> 1 )) { 21 Node<E> x = first; 22 for ( int i = 0; i < index; i++ ) 23 x = x.next; 24 return x; 25 } else { 26 Node<E> x = last; 27 for ( int i = size - 1; i > index; i-- ) 28 x = x.prev; 29 return x; 30 } 31 }
而使用迭代器或者foreach循环内部实现的代码是
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(); } } }
从代码中可以看出,迭代器相当有一个游标cursor,可以直接获取后一个或者前一个的值,它遍历的时间复杂度为O(N )