ArrayList: ensureCapacity: doubling scheme provides O(1) amortized time for add. In the process of doing n adds, the cost of making a new array and copying the old one over is n + n/2 + n/4 + n/8 + ... + 1, which equals 2*n-1. Divide by n, and it's constant time per add. LinkedList: if not using dummy nodes, special cases for add/remove from front/back. Nice to wrap the static nested class ListNode inside since no one else needs access to it. Yes, normally public vars are bad, but: 1) accessibility modifiers are meaningless inside a private nested class 2) they're acceptable if it is a data-only class (e.g. no methods other than a constructor and a simple toString) Doubly LinkedList: makes get faster if getting from the 2nd half of list (though still O(n)) remove from back is now O(1) instead of O(n) Iterators: Note that for the ArrayList and LinkedList, given a current position, operating on the previous or next element is O(1), provided we remember the necessary state for the current position. Iterators do this for us, allowing us to generically walk through an ArrayList or LinkedList with the same code and still O(1). Methods like indexOf or addAll or removeAll can be written abstractly and concisely with iterators. Call hasNext() before next() unless you are positively sure there is a next element. (Otherwise NoSuchElementException) Can't do two remove()s in a row (or a remove after iterator()) -- there must be a next() in between. (Otherwise IllegalStateException) Can't rely on the iterator's state if the list has changed since the creation of the iterator (perhaps a remove by another iterator, or an add/remove on the list). If this happens, ConcurrentModificationException The ArrayIntListIterator is a private nonstatic nested class (inner class), as in, it can refer to its enclosing class by ArrayIntList.this. On the other hand, the ListNode is a static class and cannot refer to an instance of LinkedList.