packagejava.util;importjava.util.function.Consumer;public class LinkedList
extends AbstractSequentialList
implements List, Deque, Cloneable, java.io.Serializable
{transient int size = 0;transient Nodefirst;transient Nodelast;publicLinkedList() {
}public LinkedList(Collection extends E>c) {this();
addAll(c);
}private voidlinkFirst(E e) {final Node f =first;final Node newNode = new Node<>(null, e, f);
first=newNode;if (f == null)
last=newNode;elsef.prev=newNode;
size++;
modCount++;
}voidlinkLast(E e) {final Node l =last;final Node newNode = new Node<>(l, e, null);
last=newNode;if (l == null)
first=newNode;elsel.next=newNode;
size++;
modCount++;
}void linkBefore(E e, Nodesucc) {//assert succ != null;
final Node pred =succ.prev;final Node newNode = new Node<>(pred, e, succ);
succ.prev=newNode;if (pred == null)
first=newNode;elsepred.next=newNode;
size++;
modCount++;
}private E unlinkFirst(Nodef) {//assert f == first && f != null;
final E element =f.item;final Node next =f.next;
f.item= null;
f.next= null; //help GC
first =next;if (next == null)
last= null;elsenext.prev= null;
size--;
modCount++;returnelement;
}private E unlinkLast(Nodel) {//assert l == last && l != null;
final E element =l.item;final Node prev =l.prev;
l.item= null;
l.prev= null; //help GC
last =prev;if (prev == null)
first= null;elseprev.next= null;
size--;
modCount++;returnelement;
}
E unlink(Nodex) {//assert x != null;
final E element =x.item;final Node next =x.next;final Node 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;
}
x.item= null;
size--;
modCount++;returnelement;
}publicE getFirst() {final Node f =first;if (f == null)throw newNoSuchElementException();returnf.item;
}publicE getLast() {final Node l =last;if (l == null)throw newNoSuchElementException();returnl.item;
}publicE removeFirst() {final Node f =first;if (f == null)throw newNoSuchElementException();returnunlinkFirst(f);
}publicE removeLast() {final Node l =last;if (l == null)throw newNoSuchElementException();returnunlinkLast(l);
}public voidaddFirst(E e) {
linkFirst(e);
}public voidaddLast(E e) {
linkLast(e);
}public booleancontains(Object o) {return indexOf(o) != -1;
}public intsize() {returnsize;
}public booleanadd(E e) {
linkLast(e);return true;
}public booleanremove(Object o) {if (o == null) {for (Node x = first; x != null; x =x.next) {if (x.item == null) {
unlink(x);return true;
}
}
}else{for (Node x = first; x != null; x =x.next) {if(o.equals(x.item)) {
unlink(x);return true;
}
}
}return false;
}public boolean addAll(Collection extends E>c) {returnaddAll(size, c);
}public boolean addAll(int index, Collection extends E>c) {
checkPositionIndex(index);
Object[] a=c.toArray();int numNew =a.length;if (numNew == 0)return false;
Nodepred, succ;if (index ==size) {
succ= null;
pred=last;
}else{
succ=node(index);
pred=succ.prev;
}for(Object o : a) {
@SuppressWarnings("unchecked") E e =(E) o;
Node newNode = new Node<>(pred, e, null);if (pred == null)
first=newNode;elsepred.next=newNode;
pred=newNode;
}if (succ == null) {
last=pred;
}else{
pred.next=succ;
succ.prev=pred;
}
size+=numNew;
modCount++;return true;
}public voidclear() {//Clearing all of the links between nodes is "unnecessary", but://- helps a generational GC if the discarded nodes inhabit//more than one generation//- is sure to free memory even if there is a reachable Iterator
for (Node x = first; x != null; ) {
Node next =x.next;
x.item= null;
x.next= null;
x.prev= null;
x=next;
}
first= last = null;
size= 0;
modCount++;
}//Positional Access Operations
public E get(intindex) {
checkElementIndex(index);returnnode(index).item;
}public E set(intindex, E element) {
checkElementIndex(index);
Node x =node(index);
E oldVal=x.item;
x.item=element;returnoldVal;
}public void add(intindex, E element) {
checkPositionIndex(index);if (index ==size)
linkLast(element);elselinkBefore(element, node(index));
}public E remove(intindex) {
checkElementIndex(index);returnunlink(node(index));
}private boolean isElementIndex(intindex) {return index >= 0 && index
}private boolean isPositionIndex(intindex) {return index >= 0 && index <=size;
}private String outOfBoundsMsg(intindex) {return "Index: "+index+", Size: "+size;
}private void checkElementIndex(intindex) {if (!isElementIndex(index))throw newIndexOutOfBoundsException(outOfBoundsMsg(index));
}private void checkPositionIndex(intindex) {if (!isPositionIndex(index))throw newIndexOutOfBoundsException(outOfBoundsMsg(index));
}
Node node(intindex) {//assert isElementIndex(index);
if (index < (size >> 1)) {
Node x =first;for (int i = 0; i < index; i++)
x=x.next;returnx;
}else{
Node x =last;for (int i = size - 1; i > index; i--)
x=x.prev;returnx;
}
}public intindexOf(Object o) {int index = 0;if (o == null) {for (Node x = first; x != null; x =x.next) {if (x.item == null)returnindex;
index++;
}
}else{for (Node x = first; x != null; x =x.next) {if(o.equals(x.item))returnindex;
index++;
}
}return -1;
}public intlastIndexOf(Object o) {int index =size;if (o == null) {for (Node x = last; x != null; x =x.prev) {
index--;if (x.item == null)returnindex;
}
}else{for (Node x = last; x != null; x =x.prev) {
index--;if(o.equals(x.item))returnindex;
}
}return -1;
}//Queue operations.
publicE peek() {final Node f =first;return (f == null) ? null: f.item;
}publicE element() {returngetFirst();
}publicE poll() {final Node f =first;return (f == null) ? null: unlinkFirst(f);
}publicE remove() {returnremoveFirst();
}public booleanoffer(E e) {returnadd(e);
}public booleanofferFirst(E e) {
addFirst(e);return true;
}public booleanofferLast(E e) {
addLast(e);return true;
}publicE peekFirst() {final Node f =first;return (f == null) ? null: f.item;
}publicE peekLast() {final Node l =last;return (l == null) ? null: l.item;
}publicE pollFirst() {final Node f =first;return (f == null) ? null: unlinkFirst(f);
}publicE pollLast() {final Node l =last;return (l == null) ? null: unlinkLast(l);
}public voidpush(E e) {
addFirst(e);
}publicE pop() {returnremoveFirst();
}public booleanremoveFirstOccurrence(Object o) {returnremove(o);
}public booleanremoveLastOccurrence(Object o) {if (o == null) {for (Node x = last; x != null; x =x.prev) {if (x.item == null) {
unlink(x);return true;
}
}
}else{for (Node x = last; x != null; x =x.prev) {if(o.equals(x.item)) {
unlink(x);return true;
}
}
}return false;
}public ListIterator listIterator(intindex) {
checkPositionIndex(index);return newListItr(index);
}private class ListItr implements ListIterator{private NodelastReturned;private Nodenext;private intnextIndex;private int expectedModCount =modCount;
ListItr(intindex) {//assert isPositionIndex(index);
next = (index == size) ? null: node(index);
nextIndex=index;
}public booleanhasNext() {return nextIndex
}publicE next() {
checkForComodification();if (!hasNext())throw newNoSuchElementException();
lastReturned=next;
next=next.next;
nextIndex++;returnlastReturned.item;
}public booleanhasPrevious() {return nextIndex > 0;
}publicE previous() {
checkForComodification();if (!hasPrevious())throw newNoSuchElementException();
lastReturned= next = (next == null) ?last : next.prev;
nextIndex--;returnlastReturned.item;
}public intnextIndex() {returnnextIndex;
}public intpreviousIndex() {return nextIndex - 1;
}public voidremove() {
checkForComodification();if (lastReturned == null)throw newIllegalStateException();
Node lastNext =lastReturned.next;
unlink(lastReturned);if (next ==lastReturned)
next=lastNext;elsenextIndex--;
lastReturned= null;
expectedModCount++;
}public voidset(E e) {if (lastReturned == null)throw newIllegalStateException();
checkForComodification();
lastReturned.item=e;
}public voidadd(E e) {
checkForComodification();
lastReturned= null;if (next == null)
linkLast(e);elselinkBefore(e, next);
nextIndex++;
expectedModCount++;
}public void forEachRemaining(Consumer super E>action) {
Objects.requireNonNull(action);while (modCount == expectedModCount && nextIndex
action.accept(next.item);
lastReturned=next;
next=next.next;
nextIndex++;
}
checkForComodification();
}final voidcheckForComodification() {if (modCount !=expectedModCount)throw newConcurrentModificationException();
}
}private static class Node{
E item;
Nodenext;
Nodeprev;
Node(Node prev, E element, Nodenext) {this.item =element;this.next =next;this.prev =prev;
}
}public IteratordescendingIterator() {return newDescendingIterator();
}private class DescendingIterator implements Iterator{private final ListItr itr = newListItr(size());public booleanhasNext() {returnitr.hasPrevious();
}publicE next() {returnitr.previous();
}public voidremove() {
itr.remove();
}
}
@SuppressWarnings("unchecked")private LinkedListsuperClone() {try{return (LinkedList) super.clone();
}catch(CloneNotSupportedException e) {throw newInternalError(e);
}
}publicObject clone() {
LinkedList clone =superClone();//Put clone into "virgin" state
clone.first = clone.last = null;
clone.size= 0;
clone.modCount= 0;//Initialize clone with our elements
for (Node x = first; x != null; x =x.next)
clone.add(x.item);returnclone;
}publicObject[] toArray() {
Object[] result= newObject[size];int i = 0;for (Node x = first; x != null; x =x.next)
result[i++] =x.item;returnresult;
}
@SuppressWarnings("unchecked")public T[] toArray(T[] a) {if (a.length
a=(T[])java.lang.reflect.Array.newInstance(
a.getClass().getComponentType(), size);int i = 0;
Object[] result=a;for (Node x = first; x != null; x =x.next)
result[i++] =x.item;if (a.length >size)
a[size]= null;returna;
}private static final long serialVersionUID = 876323262645176354L;private voidwriteObject(java.io.ObjectOutputStream s)throwsjava.io.IOException {//Write out any hidden serialization magic
s.defaultWriteObject();//Write out size
s.writeInt(size);//Write out all elements in the proper order.
for (Node x = first; x != null; x =x.next)
s.writeObject(x.item);
}
@SuppressWarnings("unchecked")private voidreadObject(java.io.ObjectInputStream s)throwsjava.io.IOException, ClassNotFoundException {//Read in any hidden serialization magic
s.defaultReadObject();//Read in size
int size =s.readInt();//Read in all elements in the proper order.
for (int i = 0; i < size; i++)
linkLast((E)s.readObject());
}
@Overridepublic Spliteratorspliterator() {return new LLSpliterator(this, -1, 0);
}/**A customized variant of Spliterators.IteratorSpliterator*/
static final class LLSpliterator implements Spliterator{static final int BATCH_UNIT = 1 << 10; //batch array size increment
static final int MAX_BATCH = 1 << 25; //max batch array size;
final LinkedList list; //null OK unless traversed
Node current; //current node; null until initialized
int est; //size estimate; -1 until first needed
int expectedModCount; //initialized when est set
int batch; //batch size for splits
LLSpliterator(LinkedList list, int est, intexpectedModCount) {this.list =list;this.est =est;this.expectedModCount =expectedModCount;
}final intgetEst() {int s; //force initialization
final LinkedListlst;if ((s = est) < 0) {if ((lst = list) == null)
s= est = 0;else{
expectedModCount=lst.modCount;
current=lst.first;
s= est =lst.size;
}
}returns;
}public long estimateSize() { return (long) getEst(); }public SpliteratortrySplit() {
Nodep;int s =getEst();if (s > 1 && (p = current) != null) {int n = batch +BATCH_UNIT;if (n >s)
n=s;if (n >MAX_BATCH)
n=MAX_BATCH;
Object[] a= newObject[n];int j = 0;do { a[j++] = p.item; } while ((p = p.next) != null && j
current=p;
batch=j;
est= s -j;return Spliterators.spliterator(a, 0, j, Spliterator.ORDERED);
}return null;
}public void forEachRemaining(Consumer super E>action) {
Node p; intn;if (action == null) throw newNullPointerException();if ((n = getEst()) > 0 && (p = current) != null) {
current= null;
est= 0;do{
E e=p.item;
p=p.next;
action.accept(e);
}while (p != null && --n > 0);
}if (list.modCount !=expectedModCount)throw newConcurrentModificationException();
}public boolean tryAdvance(Consumer super E>action) {
Nodep;if (action == null) throw newNullPointerException();if (getEst() > 0 && (p = current) != null) {--est;
E e=p.item;
current=p.next;
action.accept(e);if (list.modCount !=expectedModCount)throw newConcurrentModificationException();return true;
}return false;
}public intcharacteristics() {return Spliterator.ORDERED | Spliterator.SIZED |Spliterator.SUBSIZED;
}
}
}