Get into the habit of writing together! This is the 13th day of my participation in the "Nuggets Daily New Plan · April Update Challenge", click to view the event details .
LinkedList source code analysis - iterator
The iterator used in LinkedList is: ListIterator (Iterator only supports access from beginning to end), this iterator provides forward and backward iteration methods.
The main methods of ListIterator: hasPrevious(), previous(), previousIndex() --> iterative method from end to end hasNext(), next(), nextIndex() --> iterate method from beginning to end
iterator
Infrastructure source code:
private class ListItr implements ListIterator<E> {
private Node<E> lastReturned;
private Node<E> next;
private int nextIndex;
private int expectedModCount = modCount;
......
}
复制代码
-
private Node<E> lastReturned;
The node position when the next() or previous() method was last executed -
private Node<E> next;
next node -
private int nextIndex;
the location of the next node -
expectedModCount
Expected version number -
modCount
The latest version number
Iteration from start to end direction:
Source code:
public boolean hasNext() {
return nextIndex < size;
}
public E next() {
checkForComodification();
if (!hasNext())
throw new NoSuchElementException();
lastReturned = next;
next = next.next;
nextIndex++;
return lastReturned.item;
}
复制代码
-
return nextIndex < size;
Determine whether the index of the next node is less than the size of the linked list -
checkForComodification();
Check if the expected version number has changed -
if (!hasNext()) throw new NoSuchElementException();
double check -
lastReturned = next;
next represents the current node, which was assigned when the next() method was executed last time. It is assigned when the iterator is initialized on the first execution -
next = next.next;
next is the next node -
nextIndex++;
Prepare for the next iteration
Iterate from end to end
Source code:
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;
}
复制代码
-
The first iteration, next is empty, take the tail node last
-
lastReturned = next = (next == null) ? last : next.prev;
Iteration has already occurred, next is not empty, just take the previous node next.prev -
nextIndex--;
index position change
delete
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++;
}
复制代码
- `if (lastReturned == null)
throw new IllegalStateException(); Node lastNext = lastReturned.next;` lastReturned is the value that needs to be deleted in this iteration, divided into non-empty and empty cases: 1. lastReturned is empty, no next() or previous() has been actively executed , report an error directly 2. lastReturned is not empty, the value assigned when the next() or previous() method was executed last time
-
unlink(lastReturned);
delete current node -
if (next == lastReturned)
The order is traversed from the end to the beginning, and it is the first iteration and the last element is to be deleted. LastReturned = next = last is set in the previous() method, so next and lastReturned will be equal -
next = lastNext;
lastReturned is the tail node, and lastNext is null, so next is also null. If next is null in the previous() method, the tail node will be assigned to next