// 添加单个元素到链表尾部publicbooleanadd(E e){// 添加单个元素到链表尾部linkLast(e);returntrue;}// 添加单个元素到链表尾部voidlinkLast(E e){final Node<E> l = last;// 创建一个前驱节点是尾结点,后继节点是null的节点final Node<E> newNode =newNode<>(l, e, null);// 把尾结点指向新建的节点
last = newNode;// 判断l是否为空(是不是第一个元素)if(l == null)// 如果是空,说明第一次插,头结点也指向新节点
first = newNode;else// 如果不为空,原尾结点的后继节点指向新节点
l.next = newNode;// 元素个数+1
size++;// 链表操作次数+1
modCount++;}// 添加单个元素到指定位置publicvoidadd(int index, E element){// 检查要插入位置是否合法checkPositionIndex(index);// 判断是不是队尾if(index == size)// 是队尾,直接队尾插入linkLast(element);else// 不是队尾,从指定位置插入linkBefore(element,node(index));}// 返回指定元素索引处的(非空)节点。
Node<E>node(int index){// assert isElementIndex(index);// 这里做了优化,将索引是否超过元素个数的一半,来决定是从头遍历还是从尾部遍历,减少遍历次数// 没超过,从头遍历if(index <(size >>1)){
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;}}// 将数据插入到succ节点之前voidlinkBefore(E e, Node<E> succ){// assert succ != null;// succ前节点final Node<E> pred = succ.prev;// 新建一个前驱节点为succ前节点,数据为e,后继节点为succ节点的节点final Node<E> newNode =newNode<>(pred, e, succ);// 将succ的前驱节点指向新节点
succ.prev = newNode;// 判断前驱节点是否为空if(pred == null)// 说明头节点也是空,将头结点指向新节点
first = newNode;else// 不为空,将前节点的后继节点指向新节点
pred.next = newNode;// 元素个数+1
size++;// 链表操作次数+1
modCount++;}// 检查元素索引是否合法privatevoidcheckElementIndex(int index){if(!isElementIndex(index))thrownewIndexOutOfBoundsException(outOfBoundsMsg(index));}// 判断参数是否是现有元素的索引。privatebooleanisElementIndex(int index){return index >=0&& index < size;}// 检查当前位置做操作是否合法privatevoidcheckPositionIndex(int index){if(!isPositionIndex(index))thrownewIndexOutOfBoundsException(outOfBoundsMsg(index));}// 判断参数是否是迭代器或添加操作的有效位置的索引privatebooleanisPositionIndex(int index){return index >=0&& index <= size;}
5、添加多个元素
// 从尾部插入多个元素publicbooleanaddAll(Collection<?extendsE> c){returnaddAll(size, c);}// 从指定位置插入多个元素publicbooleanaddAll(int index, Collection<?extendsE> c){// 检查插入位置是否合法checkPositionIndex(index);
Object[] a = c.toArray();// 插入元素个数int numNew = a.length;// // 如果无添加元素,直接返回 false if(numNew ==0)returnfalse;// 获取index所在节点及其前驱节点
Node<E> pred, succ;if(index == size){
succ = null;
pred = last;}else{
succ =node(index);
pred = succ.prev;}// 遍历数组,将其加到index前驱节点的后面for(Object o : a){@SuppressWarnings("unchecked") E e =(E) o;// 创建一个前驱节点是pred,数据是e,后继节点为null的新节点
Node<E> newNode =newNode<>(pred, e, null);// 如果前驱节点为空if(pred == null)// 头节点指向新节点
first = newNode;// 如果前驱节点不为空else// 前驱节点的后继节点指向新节点
pred.next = newNode;// 前驱节点指向新节点
pred = newNode;}// 如果当前节点为空,说明查到队尾了if(succ == null){// 尾结点指向最后一个节点
last = pred;// 如果当前节点不为空 }else{// 则需要将新前驱节点的后继节点指向当前节点
pred.next = succ;// 将当前节点的前驱节点指向新的前驱节点
succ.prev = pred;}// 元素个数+numNew
size += numNew;// 操作次数+1
modCount++;returntrue;}
6、删除单个元素
// 删除链表第一个元素,并返回其结果(实现 Queue 接口)public E remove(){returnremoveFirst();}// 从此列表中删除并返回第一个元素(链表为空,抛 NoSuchElementException 异常)public E removeFirst(){final Node<E> f = first;if(f == null)thrownewNoSuchElementException();returnunlinkFirst(f);}// 删除链表的第一个节点private E unlinkFirst(Node<E> f){// assert f == first && f != null;final E element = f.item;final Node<E> next = f.next;// 第一个节点值置空(方便GC)
f.item = null;// 第一个节点的后继节点置空(方便GC)
f.next = null;// help GC// 将头结点只向他的后继节点
first = next;// 如果后继节点为空if(next == null)// 尾指针指向空
last = null;// 若不为空else// 将新头结点的前驱节点置空
next.prev = null;// 元素个数-1
size--;// 操作次数+1
modCount++;// 返回数据return element;}// 删除指定位置的元素public E remove(int index){// 检查指定位置是否合法checkElementIndex(index);returnunlink(node(index));}// 删除当前节点
E unlink(Node<E> x){// assert x != null;final E element = x.item;// 当前节点的后继节点final Node<E> next = x.next;// 当前节点的前驱节点final Node<E> prev = x.prev;// 前驱节点为空if(prev == null){// 说明当前节点是首节点,将头指针指向后继节点就行
first = next;// 不为空}else{// 将该节点前驱节点的后继指向该节点的后继节点
prev.next = next;// 同时将该节点的后继节点置空
x.prev = null;}// 如果其后继节点为空if(next == null){// 说明被移除的是尾节点,则将尾指针指向前驱节点
last = prev;// 若不为空 }else{// 后继节点的前驱指向前驱节点
next.prev = prev;// 当前节点的后继置空
x.next = null;}// 当前节点的值置空(GC)
x.item = null;// 元素个数-1
size--;// 操作次数+1
modCount++;return element;}// 删除链表中第一次出现的指定元素publicbooleanremove(Object o){// 要删除的数据为空,遍历删除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;}
7、查询操作
// 获取指定位置的元素public E get(int index){// 指定位置合法性校验checkElementIndex(index);returnnode(index).item;}// 设置指定位置元素,并返回旧值public E set(int index, E element){// 指定位置合法性校验checkElementIndex(index);
Node<E> x =node(index);
E oldVal = x.item;
x.item = element;return oldVal;}// 返回此列表中指定元素第一次出现的索引(for循环遍历),如果此列表不包含该元素,则返回 -1publicintindexOf(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;}