Preface
Today we will analyze a List collection class similar to it, LinkedList. However, the underlying implementation of LinkedList is linked list, and their internal implementation is quite different.
(If you want to learn programming by yourself, please search Circle T Community More industry-related information and more industry-related free video tutorials. It's totally free!
1. Overview
Interclass diagrams:
public class LinkedList<E> extends AbstractSequentialList<E> implements List<E>, Deque<E>, Cloneable, java.io.Serializable
You can see that LinkedList does not implement the Random Access interface compared to ArrayList, so we can know that it does not support random access. Next, let's look at the implementation of LinkedList
Each linked list stores first and last pointers to the head and tail nodes, respectively:
//Number of total nodes transient int size = 0; //Header node transient Node<E> first; //Tail node transient Node<E> last;
It can be found that LinkedList is based on two-way linked list and uses Node to store linked list node information.
private static class Node<E> { E item; Node<E> next; Node<E> prev; Node(Node<E> prev, E element, Node<E> next) { this.item = element; this.next = next; this.prev = prev; } }
Below is the structure of LinkedList:
2. Add
Add new elements
public void add(E e) { checkForComodification(); lastReturned = null; if (next == null) linkLast(e); else linkBefore(e, next); nextIndex++; expectedModCount++; }
Add to the tail or insert to the specified location
//Tail-insert to the tail node and set the new node as the tail node void linkLast(E e) { final Node<E> l = last; final Node<E> newNode = new Node<>(l, e, null); last = newNode; if (l == null) first = newNode; else l.next = newNode; size++; modCount++; } //Insert a new node in front of the specified node void linkBefore(E e, Node<E> succ) { // assert succ != null; final Node<E> pred = succ.prev; final Node<E> newNode = new Node<>(pred, e, succ); succ.prev = newNode; if (pred == null) first = newNode; else pred.next = newNode; size++; modCount++; }
3. Modification
public E set(int index, E element) { // Check whether index is legal checkElementIndex(index); Node<E> x = node(index); E oldVal = x.item; x.item = element; return oldVal; }
4. Delete
public boolean remove(Object o) { if (o == null) { for (Node<E> x = first; x != null; x = x.next) { if (x.item == null) { unlink(x); return true; } } } else { for (Node<E> x = first; x != null; x = x.next) { if (o.equals(x.item)) { unlink(x); return true; } } } return false; }
5. fail-fast mechanism
It is worth noting that LinkedList also has fail-fast mechanism when using iterator. Structural operation of LinkedList while iterating triggers Concurrent ModificationException exception. The specific source code is as follows:
public void add(E e) { checkForComodification(); lastReturned = null; if (next == null) linkLast(e); else linkBefore(e, next); nextIndex++; expectedModCount++; } public void set(E e) { if (lastReturned == null) throw new IllegalStateException(); checkForComodification(); lastReturned.item = e; } 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++; } // fail-fast mechanism final void checkForComodification() { if (modCount != expectedModCount) throw new ConcurrentModificationException(); }
6. Comparison with Array List
- ArrayList is based on dynamic array and LinkedList is based on bidirectional linked list.
- They are all threadless collections;
- ArrayList supports random access, LinkedList does not;
- LinkedList adds deleted elements anywhere faster than ArrayList.
7. Summary
Here is my fourth article in the Java Collection Class Source Analysis Series, from HashMap, Concurrent HashMap to ArrayList. In fact, the source analysis of these collections classes, I roughly divided into several steps to explain the analysis:
- Class Inheritance and Implementation Relations
- Internal data structure
- Some Important Methods of Addition, Deletion and Amendment
- Advantages and disadvantages of this container, security in multi-threaded environment, etc.
- Comparisons with similar containers, applicable scenarios, etc.
To sum up, there are still some other containers I haven't analyzed, but as long as we read the source code and think about the analysis according to the above idea, we can have a deeper understanding of the container, rather than just stay at the level of knowing how to use it.