Java中LinkedList实现原理
数据结构
LinkedList是基于链表结构实现,所以在LinkedList类中包含了first和last两个指针(类型为Node)。Node中包含了对prev节点、next节点的引用,这样就构成了双向的链表。
1 private static class Node<E> { 2 E item; 3 Node<E> next; 4 Node<E> prev; 5 6 Node(Node<E> prev, E element, Node<E> next) { 7 this.item = element; 8 this.next = next; 9 this.prev = prev; 10 } 11 }
存储
1.add(E e)方法
该方法首先声明一个新Node l,将链表的最后一个Node赋值给l,然后将新的Node即newNode覆盖last(或者说让last指向newNode),最后将l的next指针指向newNode。
1 //Appends the specified element to the end of this list. 2 public boolean add(E e) { 3 linkLast(e); 4 return true; 5 } 6 /** 7 * Links e as last element. 8 */ 9 void linkLast(E e) { 10 final Node<E> l = last; 11 final Node<E> newNode = new Node<>(l, e, null); 12 last = newNode; 13 if (l == null) 14 first = newNode; 15 else 16 l.next = newNode; 17 size++; 18 modCount++; 19 }
2.add(int index, E element)
该方法是在指定的index位置插入新元素。如果index位置正好等于size,则调用linkLast(element)将其插入到末尾;否则调用linkBefore(element, node(index))方法进行插入。
linkBefore中的node(index)是返回指定位置的元素。
1 public void add(int index, E element) { 2 checkPositionIndex(index); 3 if (index == size) 4 linkLast(element); 5 else 6 linkBefore(element, node(index)); 7 } 8 /** 9 * Returns the (non-null) Node at the specified element index. 10 */ 11 Node<E> node(int index) { 12 // assert isElementIndex(index); 13 // 如果要取元素的位置是整个list一半的左半边,那么从list的头开始向后遍历,遍历至要取元素的位置 14 if (index < (size >> 1)) { 15 Node<E> x = first; 16 for (int i = 0; i < index; i++) 17 x = x.next; 18 return x; 19 } 20 // 否则从list一半的右半边开始寻找,也就是从尾部开始向前遍历,遍历至要取元素的位置 21 else { 22 Node<E> x = last; 23 for (int i = size - 1; i > index; i--) 24 x = x.prev; 25 return x; 26 } 27 }
删除
1.remove(int index)
删除列表中指定位置的元素,首先检测该位置是否在该列表中存在,然后解除该元素前、后指向的元素。
1 public E remove(int index) { 2 checkElementIndex(index); 3 return unlink(node(index)); 4 } 5 E unlink(Node<E> x) { 6 // assert x != null; 7 final E element = x.item; 8 final Node<E> next = x.next; 9 final Node<E> prev = x.prev; 10 11 if (prev == null) { 12 first = next; 13 } else { 14 prev.next = next; 15 x.prev = null; 16 } 17 18 if (next == null) { 19 last = prev; 20 } else { 21 next.prev = prev; 22 x.next = null; 23 } 24 25 x.item = null; 26 size--; 27 modCount++; 28 return element; 29 }
获取
1.get(int index)
获取指定位置元素的值。同样首先判断传入位置是否越界,如果超过list的size,抛出IndexOutBoundsException异常,然后node()方法进行左半边或右半边遍历获取,add(int index, E element)中有提到,不再赘述。
1 public E get(int index) { 2 checkElementIndex(index); 3 return node(index).item; 4 }
2.getFirst()
3.getLast()
first、last是LinkedList的两个属性,判空后直接返回。
1 /** 2 * Returns the first element in this list. 3 * 4 * @return the first element in this list 5 * @throws NoSuchElementException if this list is empty 6 */ 7 public E getFirst() { 8 final Node<E> f = first; 9 if (f == null) 10 throw new NoSuchElementException(); 11 return f.item; 12 } 13 14 /** 15 * Returns the last element in this list. 16 * 17 * @return the last element in this list 18 * @throws NoSuchElementException if this list is empty 19 */ 20 public E getLast() { 21 final Node<E> l = last; 22 if (l == null) 23 throw new NoSuchElementException(); 24 return l.item; 25 }
梦想要一步步来!