/** * 链接使e作为最后一个元素。 */ voidlinkLast(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++; }
add(int index,E e):在指定位置添加元素
1 2 3 4 5 6 7 8
publicvoidadd(int index, E element){ checkPositionIndex(index); //检查索引是否处于[0-size]之间
if (index == size)//添加在链表尾部 linkLast(element); else//添加在链表中间 linkBefore(element, node(index)); }
if (index < (size >> 1)) { //在前半段 就从0开始找 Node<E> x = first; for (int i = 0; i < index; i++) x = x.next; return x; } else { //在后半段就从尾开始找 Node<E> x = last; for (int i = size - 1; i > index; i--) x = x.prev; return x; } }
//2:toArray()方法把集合的数据存到对象数组中 Object[] a = c.toArray(); int numNew = a.length; if (numNew == 0) returnfalse;
//3:得到插入位置的前驱节点和后继节点 Node<E> pred, succ; //如果插入位置为尾部,前驱节点为last,后继节点为null if (index == size) { succ = null; pred = last; } //否则,调用node()方法得到后继节点,再得到前驱节点 else { succ = node(index); pred = succ.prev; }
// 4:遍历数据将数据插入 for (Object o : a) { @SuppressWarnings("unchecked") E e = (E) o; //创建新节点 Node<E> newNode = new Node<>(pred, e, null); //如果插入位置在链表头部 if (pred == null) first = newNode; else pred.next = newNode; pred = newNode; }
//如果插入位置在尾部,重置last节点 if (succ == null) { last = pred; } //否则,将插入的链表与先前链表连接起来 else { pred.next = succ; succ.prev = pred; }
size += numNew; modCount++; returntrue; }
上面可以看出addAll方法通常包括下面四个步骤:
检查index范围是否在size之内
toArray()方法把集合的数据存到对象数组中
得到插入位置的前驱和后继节点
遍历数据,将数据插入到指定位置
addFirst(E e):将元素添加到链表头部
1 2 3
publicvoidaddFirst(E e){ linkFirst(e); }
1 2 3 4 5 6 7 8 9 10 11 12 13
privatevoidlinkFirst(E e){ final Node<E> f = first; final Node<E> newNode = new Node<>(null, e, f);//新建节点,以头节点为后继节点 first = newNode; //如果链表为空,last节点也指向该节点 if (f == null) last = newNode; //否则,将头节点的前驱指针指向新节点,也就是指向前一个元素 else f.prev = newNode; size++; modCount++; }
根据位置取数据的方法
get(int index): 根据指定索引返回数据
1 2 3 4 5 6
public E get(int index){ //检查index范围是否在size之内 checkElementIndex(index); //调用Node(index)去找到index对应的node然后返回它的值 return node(index).item; }
获取头节点(index=0)数据方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
public E getFirst(){ final Node<E> f = first; if (f == null) thrownew NoSuchElementException(); return f.item; } public E element(){ return getFirst(); } public E peek(){ final Node<E> f = first; return (f == null) ? null : f.item; }
public E peekFirst(){ final Node<E> f = first; return (f == null) ? null : f.item; }
public E getLast(){ final Node<E> l = last; if (l == null) thrownew NoSuchElementException(); return l.item; } public E peekLast(){ final Node<E> l = last; return (l == null) ? null : l.item; }
publicintindexOf(Object o){ int index = 0; if (o == null) { //从头遍历 for (Node<E> x = first; x != null; x = x.next) { if (x.item == null) return index; index++; } } else { //从头遍历 for (Node<E> x = first; x != null; x = x.next) { if (o.equals(x.item)) return index; index++; } } return -1; }
int lastIndexOf(Object o): 从尾遍历找
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
publicintlastIndexOf(Object o){ int index = size; if (o == null) { //从尾遍历 for (Node<E> x = last; x != null; x = x.prev) { index--; if (x.item == null) return index; } } else { //从尾遍历 for (Node<E> x = last; x != null; x = x.prev) { index--; if (o.equals(x.item)) return index; } } return -1; }
public E pop() { return removeFirst(); } public E remove() { return removeFirst(); } public E removeFirst() { final Node<E> f = first; if (f == null) throw new NoSuchElementException(); return unlinkFirst(f); }
removeLast(),pollLast(): 删除尾节点
1 2 3 4 5 6 7 8 9 10
public E removeLast(){ final Node<E> l = last; if (l == null) thrownew NoSuchElementException(); return unlinkLast(l); } public E pollLast(){ final Node<E> l = last; return (l == null) ? null : unlinkLast(l); }
publicbooleanremove(Object o){ //如果删除对象为null if (o == null) { //从头开始遍历 for (Node<E> x = first; x != null; x = x.next) { //找到元素 if (x.item == null) { //从链表中移除找到的元素 unlink(x); returntrue; } } } else { //从头开始遍历 for (Node<E> x = first; x != null; x = x.next) { //找到元素 if (o.equals(x.item)) { //从链表中移除找到的元素 unlink(x); returntrue; } } } returnfalse; }