All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.carrotsearch.hppcrt.lists.ObjectLinkedList Maven / Gradle / Ivy

package com.carrotsearch.hppcrt.lists;

import java.util.*;

import com.carrotsearch.hppcrt.*;
import com.carrotsearch.hppcrt.cursors.*;
import com.carrotsearch.hppcrt.predicates.*;
import com.carrotsearch.hppcrt.procedures.*;
import com.carrotsearch.hppcrt.sorting.*;

/**
 * An double-linked list of KTypes. This is an hybrid of {@link ObjectDeque} and {@link  ObjectIndexedContainer},
 * with the ability to push or remove values from either head or tail, in constant time.
 * The drawback is the double-linked list ones, i.e insert(index), remove(index) are O(N)
 * since they must traverse the collection to reach the index.
 * In addition, elements could by pushed or removed from the middle of the list without moving
 * big amounts of memory, contrary to {@link ObjectArrayList}s. Like {@link ObjectDeque}s, the double-linked list
 * can also be iterated in reverse.
 * Plus, the Iterator or reversed-iterator supports powerful methods to modify/delete/set the neighbors,
 * in replacement of the error-prone java.util.Iterator ones.
 * A compact representation is used to store and manipulate
 * all elements, without creating Objects for links. Reallocations are governed by a {@link ArraySizingStrategy}
 * and may be expensive if they move around really large chunks of memory.
 * 
 * Important note: DO NOT USE java.util.Iterator methods ! They are here only for enhanced-loop syntax. Use
 * the specialized methods of  {@link ValueIterator} or {@link DescendingValueIterator} instead !
 * 
 * @author Vincent Sonnier
 */
 @javax.annotation.Generated(date = "2014-10-25T20:54:04+0200", value = "HPPC-RT generated from: ObjectLinkedList.java") 
public class ObjectLinkedList
extends AbstractObjectCollection implements ObjectIndexedContainer, ObjectDeque, Cloneable
{
    /**
     * Default capacity if no other capacity is given in the constructor.
     */
    public final static int DEFAULT_CAPACITY = 16;

    /**
     * Internal array for storing the list. The array may be larger than the current size
     * ({@link #size()}).
     * 
         * 

Important! * The actual value in this field is always an instance of Object[], * regardless of the generic type used. The JDK is inconsistent here too: * {@link ArrayList} declares internal Object[] buffer, but * {@link ArrayDeque} declares an array of generic type objects like we do. The * tradeoff is probably minimal, but you should be aware of additional casts generated * by javac when buffer is directly accessed; these casts * may also result in exceptions at runtime. A workaround is to cast directly to * Object[] before accessing the buffer's elements, as shown * in the following code snippet.

* *
     * Object[] buf = list.buffer;
     * for (int i = 2; i <  size() + 2; i++) {
     *   doSomething(buf[i]);
     * }
     * 
*

* Direct list iteration: iterate buffer[i] for i in [2; size()+2[, but beware, it is out of order w.r.t the real list order ! *

*/ public KType[] buffer; /** * Represent the before / after nodes for each element of the buffer, * such as buffer[i] nodes are beforeAfterPointers[i] where * the 32 highest bits represent the unsigned before index in buffer : (beforeAfterPointers[i] & 0xFFFFFFFF00000000) >> 32 * the 32 lowest bits represent the unsigned after index in buffer : (beforeAfterPointers[i] & 0x00000000FFFFFFFF) */ protected long[] beforeAfterPointers; /** * Respective positions of head and tail elements of the list, * as a position in buffer, such as * after head is the actual first element of the list, * before tail is the actual last element of the list. * Technically, head and tail have hardcoded positions of 0 and 1, * and occupy buffer[0] and buffer[1] virtually. * So real buffer elements starts at index 2. */ protected static final int HEAD_POSITION = 0; protected static final int TAIL_POSITION = ObjectLinkedList.HEAD_POSITION + 1; /** * Current number of elements stored in {@link #buffer}. * Beware, the real number of elements is elementsCount - 2 */ protected int elementsCount = 2; /** * Buffer resizing strategy. */ protected final ArraySizingStrategy resizer; /** * internal pool of ValueIterator (must be created in constructor) */ protected final IteratorPool, ValueIterator> valueIteratorPool; /** * internal pool of DescendingValueIterator (must be created in constructor) */ protected final IteratorPool, DescendingValueIterator> descendingValueIteratorPool; /** * Create with default sizing strategy and initial capacity for storing * {@value #DEFAULT_CAPACITY} elements. * * @see BoundedProportionalArraySizingStrategy */ public ObjectLinkedList() { this(ObjectLinkedList.DEFAULT_CAPACITY); } /** * Create with default sizing strategy and the given initial capacity. * * @see BoundedProportionalArraySizingStrategy */ public ObjectLinkedList(final int initialCapacity) { this(initialCapacity, new BoundedProportionalArraySizingStrategy()); } /** * Create with a custom buffer resizing strategy. */ public ObjectLinkedList(final int initialCapacity, final ArraySizingStrategy resizer) { assert initialCapacity >= 0 : "initialCapacity must be >= 0: " + initialCapacity; assert resizer != null; this.resizer = resizer; final int internalSize = resizer.round(initialCapacity); //allocate internal buffer this.buffer = Internals.newArray(internalSize + 2); this.beforeAfterPointers = new long[internalSize + 2]; //initialize this.elementsCount = 2; //initialize head and tail: initially, they are linked to each other. this.beforeAfterPointers[ObjectLinkedList.HEAD_POSITION] = (((long) ObjectLinkedList.HEAD_POSITION << 32) | ObjectLinkedList.TAIL_POSITION); this.beforeAfterPointers[ObjectLinkedList.TAIL_POSITION] = (((long) ObjectLinkedList.HEAD_POSITION << 32) | ObjectLinkedList.TAIL_POSITION); this.valueIteratorPool = new IteratorPool, ValueIterator>( new ObjectFactory() { @Override public ValueIterator create() { return new ValueIterator(); } @Override public void initialize(final ValueIterator obj) { obj.internalIndex = -1; obj.cursor.index = -1; obj.cursor.value = ObjectLinkedList.this.defaultValue; obj.buffer = ObjectLinkedList.this.buffer; obj.pointers = ObjectLinkedList.this.beforeAfterPointers; obj.internalPos = ObjectLinkedList.HEAD_POSITION; } @Override public void reset(final ValueIterator obj) { // for GC sake obj.buffer = null; obj.pointers = null; } }); this.descendingValueIteratorPool = new IteratorPool, DescendingValueIterator>( new ObjectFactory() { @Override public DescendingValueIterator create() { return new DescendingValueIterator(); } @Override public void initialize(final DescendingValueIterator obj) { obj.internalIndex = ObjectLinkedList.this.size(); obj.cursor.index = ObjectLinkedList.this.size(); obj.cursor.value = ObjectLinkedList.this.defaultValue; obj.buffer = ObjectLinkedList.this.buffer; obj.pointers = ObjectLinkedList.this.beforeAfterPointers; obj.internalPos = ObjectLinkedList.TAIL_POSITION; } @Override public void reset(final DescendingValueIterator obj) { // for GC sake obj.buffer = null; obj.pointers = null; } }); } /** * Creates a new list from elements of another container. */ public ObjectLinkedList(final ObjectContainer container) { this(container.size()); addAll(container); } /** * {@inheritDoc} */ @Override public void add(final KType e1) { addLast(e1); } /** * Appends two elements at the end of the list. To add more than two elements, * use add (vararg-version) or access the buffer directly (tight * loop). */ public void add(final KType e1, final KType e2) { ensureBufferSpace(2); insertAfterPosNoCheck(e1, ((int) (this.beforeAfterPointers[ObjectLinkedList.TAIL_POSITION] >> 32)));; insertAfterPosNoCheck(e2, ((int) (this.beforeAfterPointers[ObjectLinkedList.TAIL_POSITION] >> 32)));; } public void addLast(final KType... elements) { addLast(elements, 0, elements.length); } /** * Add all elements from a range of given array to the list. */ public void addLast(final KType[] elements, final int start, final int length) { assert length + start <= elements.length : "Length is smaller than required"; ensureBufferSpace(length); final long[] beforeAfterPointers = this.beforeAfterPointers; for (int i = 0; i < length; i++) { insertAfterPosNoCheck(elements[start + i], ((int) (beforeAfterPointers[ObjectLinkedList.TAIL_POSITION] >> 32))); } } /** * Add all elements from a range of given array to the list, equivalent to addLast() */ public void add(final KType[] elements, final int start, final int length) { addLast(elements, start, length); } /** * Vararg-signature method for adding elements at the end of the list. *

This method is handy, but costly if used in tight loops (anonymous * array passing)

*/ public void add(final KType... elements) { addLast(elements, 0, elements.length); } /** * Adds all elements from another container, equivalent to addLast() */ public int addAll(final ObjectContainer container) { return addLast(container); } /** * Adds all elements from another iterable, equivalent to addLast() */ public int addAll(final Iterable> iterable) { return addLast(iterable); } /** * {@inheritDoc} */ @Override public void insert(final int index, final KType e1) { assert (index >= 0 && index <= size()) : "Index " + index + " out of bounds [" + 0 + ", " + size() + "]."; ensureBufferSpace(1); if (index == 0) { insertAfterPosNoCheck(e1, ObjectLinkedList.HEAD_POSITION); } else { insertAfterPosNoCheck(e1, gotoIndex(index - 1)); } } /** * {@inheritDoc} */ @Override public KType get(final int index) { assert (index >= 0 && index < size()) : "Index " + index + " out of bounds [" + 0 + ", " + size() + ")."; //get object at pos currentPos in buffer return this.buffer[gotoIndex(index)]; } /** * {@inheritDoc} */ @Override public KType set(final int index, final KType e1) { assert (index >= 0 && index < size()) : "Index " + index + " out of bounds [" + 0 + ", " + size() + ")."; //get object at pos currentPos in buffer final int pos = gotoIndex(index); //keep the previous value final KType elem = this.buffer[pos]; //new value this.buffer[pos] = e1; return elem; } /** * {@inheritDoc} */ @Override public KType remove(final int index) { assert (index >= 0 && index < size()) : "Index " + index + " out of bounds [" + 0 + ", " + size() + ")."; //get object at pos currentPos in buffer final int currentPos = gotoIndex(index); final KType elem = this.buffer[currentPos]; //remove removeAtPosNoCheck(currentPos); return elem; } /** * {@inheritDoc} */ @Override public void removeRange(final int fromIndex, final int toIndex) { assert (fromIndex >= 0 && fromIndex <= size()) : "Index " + fromIndex + " out of bounds [" + 0 + ", " + size() + ")."; assert (toIndex >= 0 && toIndex <= size()) : "Index " + toIndex + " out of bounds [" + 0 + ", " + size() + "]."; assert fromIndex <= toIndex : "fromIndex must be <= toIndex: " + fromIndex + ", " + toIndex; //goto pos int currentPos = gotoIndex(fromIndex); //start removing size elements... final int size = toIndex - fromIndex; int count = 0; while (count < size) { currentPos = removeAtPosNoCheck(currentPos); count++; } } /** * {@inheritDoc} */ @Override public int removeFirstOccurrence(final KType e1) { final long[] pointers = this.beforeAfterPointers; final KType[] buffer = this.buffer; int currentPos = ((int) (pointers[ObjectLinkedList.HEAD_POSITION] & 0x00000000FFFFFFFFL)); int count = 0; while (currentPos != ObjectLinkedList.TAIL_POSITION) { if (((e1) == null ? (buffer[currentPos]) == null : (e1).equals((buffer[currentPos])))) { removeAtPosNoCheck(currentPos); return count; } //increment currentPos = ((int) (pointers[currentPos] & 0x00000000FFFFFFFFL)); count++; } return -1; } /** * {@inheritDoc} */ @Override public int removeLastOccurrence(final KType e1) { final long[] pointers = this.beforeAfterPointers; final KType[] buffer = this.buffer; final int size = size(); int currentPos = ((int) (pointers[ObjectLinkedList.TAIL_POSITION] >> 32)); int count = 0; while (currentPos != ObjectLinkedList.HEAD_POSITION) { if (((e1) == null ? (buffer[currentPos]) == null : (e1).equals((buffer[currentPos])))) { removeAtPosNoCheck(currentPos); return size - count - 1; } currentPos = ((int) (pointers[currentPos] >> 32)); count++; } return -1; } /** * {@inheritDoc} */ @Override public int removeAllOccurrences(final KType e1) { final KType[] buffer = this.buffer; int deleted = 0; //real elements starts in postion 2. int pos = 2; //directly iterate the buffer, so out of order. while (pos < this.elementsCount) { if (((e1) == null ? (buffer[pos]) == null : (e1).equals((buffer[pos])))) { //each time a pos is removed, pos is patched with the last element, //so continue to test the same position removeAtPosNoCheck(pos); deleted++; } else { pos++; } } //end while return deleted; } /** * {@inheritDoc} */ @Override public boolean contains(final KType e1) { return indexOf(e1) >= 0; } /** * {@inheritDoc} */ @Override public int indexOf(final KType e1) { final long[] pointers = this.beforeAfterPointers; final KType[] buffer = this.buffer; int currentPos = ((int) (pointers[ObjectLinkedList.HEAD_POSITION] & 0x00000000FFFFFFFFL)); int count = 0; while (currentPos != ObjectLinkedList.TAIL_POSITION) { if (((e1) == null ? (buffer[currentPos]) == null : (e1).equals((buffer[currentPos])))) { return count; } currentPos = ((int) (pointers[currentPos] & 0x00000000FFFFFFFFL)); count++; } return -1; } /** * {@inheritDoc} */ @Override public int lastIndexOf(final KType e1) { final long[] pointers = this.beforeAfterPointers; final KType[] buffer = this.buffer; int currentPos = ((int) (pointers[ObjectLinkedList.TAIL_POSITION] >> 32)); int count = 0; while (currentPos != ObjectLinkedList.HEAD_POSITION) { if (((e1) == null ? (buffer[currentPos]) == null : (e1).equals((buffer[currentPos])))) { return size() - count - 1; } currentPos = ((int) (pointers[currentPos] >> 32)); count++; } return -1; } /** * Increases the capacity of this instance, if necessary, to ensure * that it can hold at least the number of elements specified by * the minimum capacity argument. */ public void ensureCapacity(final int minCapacity) { if (minCapacity > this.buffer.length) { ensureBufferSpace(minCapacity - size()); } } /** * Ensures the internal buffer has enough free slots to store * expectedAdditions. Increases internal buffer size if needed. * @return true if a reallocation occurs */ protected boolean ensureBufferSpace(final int expectedAdditions) { final int bufferLen = (this.buffer == null ? 0 : this.buffer.length); if (this.elementsCount > bufferLen - expectedAdditions) { final int newSize = this.resizer.grow(bufferLen, this.elementsCount, expectedAdditions); assert newSize >= this.elementsCount + expectedAdditions : "Resizer failed to" + " return sensible new size: " + newSize + " <= " + (this.elementsCount + expectedAdditions); //the first 2 slots are head/tail placeholders final KType[] newBuffer = Internals.newArray(newSize + 2); final long[] newPointers = new long[newSize + 2]; if (bufferLen > 0) { System.arraycopy(this.buffer, 0, newBuffer, 0, this.buffer.length); System.arraycopy(this.beforeAfterPointers, 0, newPointers, 0, this.beforeAfterPointers.length); } this.buffer = newBuffer; this.beforeAfterPointers = newPointers; return true; } return false; } /** * {@inheritDoc} */ @Override public int size() { return this.elementsCount - 2; } /** * {@inheritDoc} */ @Override public int capacity() { return this.buffer.length - 2; } /** * Sets the number of stored elements to zero. */ @Override public void clear() { ObjectArrays.blankArray(this.buffer, 0, this.elementsCount); //the first two are placeholders this.elementsCount = 2; //rebuild head/tail this.beforeAfterPointers[ObjectLinkedList.HEAD_POSITION] = (((long) ObjectLinkedList.HEAD_POSITION << 32) | ObjectLinkedList.TAIL_POSITION); this.beforeAfterPointers[ObjectLinkedList.TAIL_POSITION] = (((long) ObjectLinkedList.HEAD_POSITION << 32) | ObjectLinkedList.TAIL_POSITION); } /** * {@inheritDoc} */ @Override public KType[] toArray(final KType[] target) { //Return in-order final long[] pointers = this.beforeAfterPointers; final KType[] buffer = this.buffer; int index = 0; int currentPos = ((int) (pointers[ObjectLinkedList.HEAD_POSITION] & 0x00000000FFFFFFFFL)); while (currentPos != ObjectLinkedList.TAIL_POSITION) { target[index] = buffer[currentPos]; //increment both currentPos = ((int) (pointers[currentPos] & 0x00000000FFFFFFFFL)); index++; } return target; } /** * Clone this object. The returned clone will use the same resizing strategy. * It also realizes a trim-to- this.size() in the process. */ @Override public ObjectLinkedList clone() { /* */ @SuppressWarnings("unchecked") /* */ final ObjectLinkedList cloned = new ObjectLinkedList(this.size(), this.resizer); cloned.addAll(this); cloned.defaultValue = this.defaultValue; return cloned; } /** * {@inheritDoc} */ @Override public int hashCode() { final long[] pointers = this.beforeAfterPointers; final KType[] buffer = this.buffer; int h = 1; int currentPos = ((int) (pointers[ObjectLinkedList.HEAD_POSITION] & 0x00000000FFFFFFFFL)); while (currentPos != ObjectLinkedList.TAIL_POSITION) { h = 31 * h + Internals.rehash(buffer[currentPos]); //increment currentPos = ((int) (pointers[currentPos] & 0x00000000FFFFFFFFL)); } return h; } /** * {@inheritDoc} */ @Override /* */ @SuppressWarnings("unchecked") /* */ public boolean equals(final Object obj) { if (obj != null) { if (obj == this) { return true; } final long[] pointers = this.beforeAfterPointers; final KType[] buffer = this.buffer; if (obj instanceof ObjectLinkedList) { final ObjectLinkedList other = (ObjectLinkedList) obj; if (other.size() != this.size()) { return false; } final long[] pointersOther = other.beforeAfterPointers; final KType[] bufferOther = (KType[]) other.buffer; //compare index/index int currentPos = ((int) (pointers[ObjectLinkedList.HEAD_POSITION] & 0x00000000FFFFFFFFL)); int currentPosOther = ((int) (pointersOther[ObjectLinkedList.HEAD_POSITION] & 0x00000000FFFFFFFFL)); while (currentPos != ObjectLinkedList.TAIL_POSITION && currentPosOther != ObjectLinkedList.TAIL_POSITION) { if (!((buffer[currentPos]) == null ? (bufferOther[currentPosOther]) == null : (buffer[currentPos]).equals((bufferOther[currentPosOther])))) { return false; } //increment both currentPos = ((int) (pointers[currentPos] & 0x00000000FFFFFFFFL)); currentPosOther = ((int) (pointersOther[currentPosOther] & 0x00000000FFFFFFFFL)); } return true; } else if (obj instanceof ObjectDeque) { final ObjectDeque other = (ObjectDeque) obj; if (other.size() != this.size()) { return false; } //compare index/index int currentPos = ((int) (pointers[ObjectLinkedList.HEAD_POSITION] & 0x00000000FFFFFFFFL)); //request a pooled iterator final Iterator> it = other.iterator(); ObjectCursor c; //iterate over the linkedList while (currentPos != ObjectLinkedList.TAIL_POSITION) { c = it.next(); if (!((buffer[currentPos]) == null ? (c.value) == null : (buffer[currentPos]).equals((c.value)))) { //if iterator was pooled, recycled it if (it instanceof AbstractIterator) { ((AbstractIterator) it).release(); } return false; } //increment both currentPos = ((int) (pointers[currentPos] & 0x00000000FFFFFFFFL)); } //end while //if iterator was pooled, recycled it if (it instanceof AbstractIterator) { ((AbstractIterator) it).release(); } return true; } else if (obj instanceof ObjectIndexedContainer) { final ObjectIndexedContainer other = (ObjectIndexedContainer) obj; if (other.size() != this.size()) { return false; } //compare index/index int currentPos = ((int) (pointers[ObjectLinkedList.HEAD_POSITION] & 0x00000000FFFFFFFFL)); int index = 0; while (currentPos != ObjectLinkedList.TAIL_POSITION) { if (!((buffer[currentPos]) == null ? (other.get(index)) == null : (buffer[currentPos]).equals((other.get(index))))) { return false; } //increment both currentPos = ((int) (pointers[currentPos] & 0x00000000FFFFFFFFL)); index++; } return true; } } return false; } /** * Traverse the list to index, return the position in buffer * when reached. This is a O(n) operation !. * @param index * @return */ protected int gotoIndex(final int index) { int currentPos = ObjectLinkedList.TAIL_POSITION; int currentIndex = -1; final long[] pointers = this.beforeAfterPointers; //A) Search by head if (index <= (this.elementsCount / 2.0)) { //reach index - 1 position, from head, insert after currentIndex = 0; currentPos = ((int) (pointers[ObjectLinkedList.HEAD_POSITION] & 0x00000000FFFFFFFFL)); while (currentIndex < index && currentPos != ObjectLinkedList.TAIL_POSITION) { currentPos = ((int) (pointers[currentPos] & 0x00000000FFFFFFFFL)); currentIndex++; } } else { //B) short path to go from tail, //reach index - 1 position, from head, insert after currentIndex = size() - 1; currentPos = ((int) (pointers[ObjectLinkedList.TAIL_POSITION] >> 32)); while (currentIndex > index && currentPos != ObjectLinkedList.HEAD_POSITION) { currentPos = ((int) (pointers[currentPos] >> 32)); currentIndex--; } } //assert currentIndex == index; return currentPos; } /** * Insert after position insertionPos. * Insert an element just after insertionPos element. * @param e1 * @param insertionPos */ private void insertAfterPosNoCheck(final KType e1, final int insertionPos) { final long[] pointers = this.beforeAfterPointers; //we insert between insertionPos and its successor, keep reference of the successor final int nextAfterInsertionPos = ((int) (pointers[insertionPos] & 0x00000000FFFFFFFFL)); //the new element is taken at the end of the buffer, at elementsCount. //link it as: [insertionPos | nextAfterInsertionPos] pointers[this.elementsCount] = (((long) insertionPos << 32) | nextAfterInsertionPos); //re-link insertionPos element (left) : //[.. | nextAfterInsertionPos] ==> [.. | elementsCount] pointers[insertionPos] = (this.elementsCount | (pointers[insertionPos] & 0xFFFFFFFF00000000L)); //re-link nextAfterInsertionPos element (right) //[insertionPos |..] ==> [elementsCount | ..] pointers[nextAfterInsertionPos] = (((long) this.elementsCount << 32) | (pointers[nextAfterInsertionPos] & 0x00000000FFFFFFFFL)); //really add element to buffer at position elementsCount this.buffer[this.elementsCount] = e1; this.elementsCount++; } /** * Remove element at position removalPos in buffer * @param removalPos * @return the next valid position after the removal, supposing head to tail iteration. */ private int removeAtPosNoCheck(final int removalPos) { final long[] pointers = this.beforeAfterPointers; //A) Unlink removalPos properly final int beforeRemovalPos = ((int) (pointers[removalPos] >> 32)); final int afterRemovalPos = ((int) (pointers[removalPos] & 0x00000000FFFFFFFFL)); //the element before element removalPos is now linked to afterRemovalPos : //[... | removalPos] ==> [... | afterRemovalPos] pointers[beforeRemovalPos] = (afterRemovalPos | (pointers[beforeRemovalPos] & 0xFFFFFFFF00000000L)); //the element after element removalPos is now linked to beforeRemovalPos : //[removalPos | ...] ==> [beforeRemovalPos | ...] pointers[afterRemovalPos] = (((long) beforeRemovalPos << 32) | (pointers[afterRemovalPos] & 0x00000000FFFFFFFFL)); //if the removed element is not the last of the buffer, move it to the "hole" created at removalPos if (removalPos != this.elementsCount - 1) { //B) To keep the buffer compact, take now the last buffer element and put it to removalPos //keep the positions of the last buffer element, because we'll need to re-link it after //moving the element elementsCount - 1 final int beforeLastElementPos = ((int) (pointers[this.elementsCount - 1] >> 32)); final int afterLastElementPos = ((int) (pointers[this.elementsCount - 1] & 0x00000000FFFFFFFFL)); //To keep the buffer compact, take now the last buffer element and put it to removalPos this.buffer[removalPos] = this.buffer[this.elementsCount - 1]; pointers[removalPos] = pointers[this.elementsCount - 1]; //B-2) Re-link the elements that where neighbours of "elementsCount - 1" to point to removalPos element now //update the pointer of the before the last element = [... | elementsCount - 1] ==> [... | removalPos] pointers[beforeLastElementPos] = (removalPos | (pointers[beforeLastElementPos] & 0xFFFFFFFF00000000L)); //update the pointer of the after the last element = [... | elementsCount - 1] ==> [... | removalPos] pointers[afterLastElementPos] = (((long) removalPos << 32) | (pointers[afterLastElementPos] & 0x00000000FFFFFFFFL)); } //for GC this.buffer[this.elementsCount - 1] = null; this.elementsCount--; return ((int) (pointers[beforeRemovalPos] & 0x00000000FFFFFFFFL)); } /** * An iterator implementation for {@link ObjectLinkedList#iterator}. *
     * 
     * Important note: DO NOT USE java.util.Iterator methods ! They are here only for enhanced-loop syntax and compatibility. Use
     * the specialized methods instead !
     * Iteration example:
     * 
*
     *   ObjectLinkedList.ValueIterator it = null;
     *   try
     *   {
     *       for (it = list.iterator().gotoNext(); !it.isTail(); it.gotoNext())
     *       {
     *
     *          // do something
     *       }
     *   }
     *   finally
     *   {
     *       //do not forget to release the iterator !
     *       it.release();
     *   }
     * 
*/ public class ValueIterator extends AbstractIterator> { public final ObjectCursor cursor; protected final ObjectCursor tmpCursor; KType[] buffer; int internalPos; long[] pointers; int internalIndex = -1; public ValueIterator() { this.cursor = new ObjectCursor(); this.tmpCursor = new ObjectCursor(); this.internalIndex = -1; this.cursor.index = -1; this.cursor.value = ObjectLinkedList.this.defaultValue; this.buffer = ObjectLinkedList.this.buffer; this.pointers = ObjectLinkedList.this.beforeAfterPointers; this.internalPos = ObjectLinkedList.HEAD_POSITION; } /** * * DO NOT USE, unsupported operation. * */ @Override protected ObjectCursor fetch() { throw new UnsupportedOperationException(); } /** * * DO NOT USE directly, It is here only for the enhanced for loop syntax support. * */ @Override public boolean hasNext() { final int nextPos = ((int) (this.pointers[this.internalPos] & 0x00000000FFFFFFFFL)); //auto-release when hasNext() returns false; if (nextPos == ObjectLinkedList.TAIL_POSITION && this.iteratorPool != null && !this.isFree) { this.iteratorPool.release(this); this.isFree = true; } return nextPos != ObjectLinkedList.TAIL_POSITION; } /** * * DO NOT USE directly, It is here only for the enhanced for loop syntax support. * */ @Override public ObjectCursor next() { //search for the next position final int nextPos = ((int) (this.pointers[this.internalPos] & 0x00000000FFFFFFFFL)); //we are at tail already. if (nextPos == ObjectLinkedList.TAIL_POSITION) { throw new NoSuchElementException(); } //point to next this.internalPos = nextPos; this.internalIndex++; this.cursor.index = this.internalIndex; this.cursor.value = this.buffer[nextPos]; return this.cursor; } ///////////////////////// Forward iteration methods ////////////////////////////////////// /** * True is iterator points to the "head", i.e such as gotoNext() point to the first * element, with respect to the forward iteration. * @return */ public boolean isHead() { return this.internalPos == ObjectLinkedList.HEAD_POSITION; } /** * True is iterator points to the "tail", i.e such as gotoPrevious() point to the last * element, with respect to the forward iteration. * @return */ public boolean isTail() { return this.internalPos == ObjectLinkedList.TAIL_POSITION; } /** * True if the iterator points to the first element * with respect to the forward iteration. Always true if the list is empty. */ public boolean isFirst() { final int nextPos = ((int) (this.pointers[ObjectLinkedList.HEAD_POSITION] & 0x00000000FFFFFFFFL)); return (nextPos == ObjectLinkedList.TAIL_POSITION) ? true : (nextPos == this.internalPos); } /** * True if the iterator points to the last element * with respect to the forward iteration. Always true if the list is empty. */ public boolean isLast() { final int nextPos = ((int) (this.pointers[ObjectLinkedList.TAIL_POSITION] >> 32)); return (nextPos == ObjectLinkedList.HEAD_POSITION) ? true : (nextPos == this.internalPos); } /** * Move the iterator to the "head", returning itself for chaining. */ public ValueIterator gotoHead() { this.internalIndex = -1; this.internalPos = ObjectLinkedList.HEAD_POSITION; //update cursor this.cursor.index = -1; this.cursor.value = ObjectLinkedList.this.defaultValue; return this; } /** * Move the iterator to the "tail", returning itself for chaining. */ public ValueIterator gotoTail() { this.internalIndex = ObjectLinkedList.this.size(); this.internalPos = ObjectLinkedList.TAIL_POSITION; //update cursor this.cursor.index = this.internalIndex; this.cursor.value = ObjectLinkedList.this.defaultValue; return this; } /** * Move the iterator to the next element, with respect to the forward iteration, * returning itself for chaining. When "tail" is reached, gotoNext() stays in place, at tail. */ public ValueIterator gotoNext() { this.internalPos = ((int) (this.pointers[this.internalPos] & 0x00000000FFFFFFFFL)); if (this.internalPos == ObjectLinkedList.TAIL_POSITION) { this.internalIndex = ObjectLinkedList.this.size(); //update cursor this.cursor.index = this.internalIndex; this.cursor.value = ObjectLinkedList.this.defaultValue; } else { this.internalIndex++; //update cursor this.cursor.index = this.internalIndex; this.cursor.value = this.buffer[this.internalPos]; } return this; } /** * Move the iterator to the previous element, with respect to the forward iteration, * returning itself for chaining. When "head" is reached, gotoPrevious() stays in place, at head. */ public ValueIterator gotoPrevious() { this.internalPos = ((int) (this.pointers[this.internalPos] >> 32)); if (this.internalPos == ObjectLinkedList.HEAD_POSITION) { this.internalIndex = -1; this.cursor.index = this.internalIndex; this.cursor.value = ObjectLinkedList.this.defaultValue; } else { this.internalIndex--; this.cursor.index = this.internalIndex; this.cursor.value = this.buffer[this.internalPos]; } return this; } /** * Get the next element value with respect to the forward iteration, * without moving the iterator. * Returns null if no such element exists. */ public ObjectCursor getNext() { final int nextPos = ((int) (this.pointers[this.internalPos] & 0x00000000FFFFFFFFL)); if (nextPos == ObjectLinkedList.TAIL_POSITION) { return null; } //use the temporary Cursor in order to protect the iterator cursor this.tmpCursor.index = this.internalIndex + 1; this.tmpCursor.value = this.buffer[nextPos]; return this.tmpCursor; } /** * Get the previous element value with respect to the forward iteration, * Returns null if no such element exists. */ public ObjectCursor getPrevious() { final int beforePos = ((int) (this.pointers[this.internalPos] >> 32)); if (beforePos == ObjectLinkedList.HEAD_POSITION) { return null; } //use the temporary Cursor in order to protect the iterator cursor this.tmpCursor.index = this.internalIndex - 1; this.tmpCursor.value = this.buffer[beforePos]; return this.tmpCursor; } /** * Removes the next element, without moving the iterator. * Returns the removed element cursor, or null if the removal failed. * (because there is no element left after) */ public ObjectCursor removeNext() { final int nextPos = ((int) (this.pointers[this.internalPos] & 0x00000000FFFFFFFFL)); if (nextPos == ObjectLinkedList.TAIL_POSITION) { return null; } //store the next positions in returned cursor this.tmpCursor.index = this.internalIndex + 1; this.tmpCursor.value = this.buffer[nextPos]; // the current position is unaffected. removeAtPosNoCheck(nextPos); return this.tmpCursor; } /** * Removes the previous element, without moving the iterator. * Returns the removed element cursor, or null if the removal failed. * (because there is no element left before) */ public ObjectCursor removePrevious() { final int previousPos = ((int) (this.pointers[this.internalPos] >> 32)); if (previousPos == ObjectLinkedList.HEAD_POSITION) { return null; } //store the next positions in returned cursor this.tmpCursor.index = this.internalIndex - 1; this.tmpCursor.value = this.buffer[previousPos]; //update the new current position this.internalPos = removeAtPosNoCheck(previousPos); //the internal index changed, update the cursor index, the buffer stays unchanged. this.internalIndex--; this.cursor.index = this.internalIndex; return this.tmpCursor; } /** * Insert e1 before the iterator position, without moving the iterator. */ public void insertBefore(final KType e1) { //protect the head if (this.internalPos != ObjectLinkedList.HEAD_POSITION) { //assure growing, and grab the new arrays references if needed if (ensureBufferSpace(1)) { this.pointers = ObjectLinkedList.this.beforeAfterPointers; this.buffer = ObjectLinkedList.this.buffer; } final int beforePos = ((int) (this.pointers[this.internalPos] >> 32)); //we insert after the previous insertAfterPosNoCheck(e1, beforePos); //the internal index changed, update the cursor index, the buffer stays unchanged. this.internalIndex++; this.cursor.index = this.internalIndex; } } /** * Insert e1 after the iterator position, without moving the iterator. */ public void insertAfter(final KType e1) { //protect the tail if (this.internalPos != ObjectLinkedList.TAIL_POSITION) { //assure growing, and grab the new arrays references if needed if (ensureBufferSpace(1)) { this.pointers = ObjectLinkedList.this.beforeAfterPointers; this.buffer = ObjectLinkedList.this.buffer; } //we insert after us insertAfterPosNoCheck(e1, this.internalPos); } //the internal index doesn't change... } /** * Set e1 to the current iterator position, without moving the iterator, * while returning the previous value. If no such previous value exists, returns the default value. */ public KType set(final KType e1) { KType elem = ObjectLinkedList.this.defaultValue; //protect the heads/tails if (this.internalPos != ObjectLinkedList.HEAD_POSITION && this.internalPos != ObjectLinkedList.TAIL_POSITION) { elem = this.buffer[this.internalPos]; this.buffer[this.internalPos] = e1; } return elem; } /** * Delete the current iterator position, and moves to the next valid * element after this removal, with respect to the forward iteration. * Returns the iterator itself for chaining. */ public ValueIterator delete() { //protect the heads/tails if (this.internalPos != ObjectLinkedList.HEAD_POSITION && this.internalPos != ObjectLinkedList.TAIL_POSITION) { this.internalPos = removeAtPosNoCheck(this.internalPos); //update cursor returned by iterator this.cursor.value = this.buffer[this.internalPos]; //internal index doesn't change } return this; } } /** * An iterator implementation for {@link ObjectLinkedList#descendingIterator()}. *

     * Important note: DO NOT USE java.util.Iterator methods ! They are here only for compatibility. Use
     * the specialized methods instead !
     * 
* Iteration example: * *
     *   ObjectLinkedList.ValueIterator it = null;
     *   try
     *   {
     *       for (it = list.iterator().gotoNext(); !it.isTail(); it.gotoNext())
     *       {
     *          // do something
     *       }
     *   }
     *   finally
     *   {
     *       //do not forget to release the iterator !
     *       it.release();
     *   }
     * 
*/ public final class DescendingValueIterator extends ValueIterator { public DescendingValueIterator() { super(); this.internalIndex = ObjectLinkedList.this.size(); this.cursor.index = ObjectLinkedList.this.size(); this.cursor.value = ObjectLinkedList.this.defaultValue; this.buffer = ObjectLinkedList.this.buffer; this.pointers = ObjectLinkedList.this.beforeAfterPointers; this.internalPos = ObjectLinkedList.TAIL_POSITION; } /** * * DO NOT USE. * */ @Override public boolean hasNext() { final int nextPos = ((int) (this.pointers[this.internalPos] >> 32)); //auto-release when hasNext() returns false; if (nextPos == ObjectLinkedList.HEAD_POSITION && this.iteratorPool != null && !this.isFree) { this.iteratorPool.release(this); this.isFree = true; } return nextPos != ObjectLinkedList.HEAD_POSITION; } /** * * DO NOT USE directly, It is here only for the enhanced for loop syntax support. * */ @Override public ObjectCursor next() { //search for the next position final int nextPos = ((int) (this.pointers[this.internalPos] >> 32)); //we are at tail already. if (nextPos == ObjectLinkedList.HEAD_POSITION) { throw new NoSuchElementException(); } //point to next this.internalPos = nextPos; this.internalIndex--; this.cursor.index = this.internalIndex; this.cursor.value = this.buffer[nextPos]; return this.cursor; } ///////////////////////// Descending iteration methods ////////////////////////////////////// /** * {@inheritDoc} */ @Override public boolean isHead() { return super.isTail(); } /** * {@inheritDoc} */ @Override public boolean isTail() { return super.isHead(); } /** * {@inheritDoc} */ @Override public boolean isFirst() { return super.isLast(); } /** * {@inheritDoc} */ @Override public boolean isLast() { return super.isFirst(); } /** * {@inheritDoc} */ @Override public ValueIterator gotoHead() { return super.gotoTail(); } /** * {@inheritDoc} */ @Override @SuppressWarnings("unchecked") public DescendingValueIterator gotoTail() { return (DescendingValueIterator) super.gotoHead(); } /** * {@inheritDoc} */ @Override @SuppressWarnings("unchecked") public DescendingValueIterator gotoNext() { return (DescendingValueIterator) super.gotoPrevious(); } /** * {@inheritDoc} */ @Override @SuppressWarnings("unchecked") public DescendingValueIterator gotoPrevious() { return (DescendingValueIterator) super.gotoNext(); } /** * {@inheritDoc} */ @Override public ObjectCursor getNext() { return super.getPrevious(); } /** * {@inheritDoc} */ @Override public ObjectCursor getPrevious() { return super.getNext(); } /** * {@inheritDoc} */ @Override public ObjectCursor removeNext() { return super.removePrevious(); } /** * {@inheritDoc} */ @Override public ObjectCursor removePrevious() { return super.removeNext(); } /** * {@inheritDoc} */ @Override public void insertBefore(final KType e1) { super.insertAfter(e1); } /** * {@inheritDoc} */ @Override public void insertAfter(final KType e1) { super.insertBefore(e1); } /** * {@inheritDoc} */ @Override public DescendingValueIterator delete() { if (this.internalPos != ObjectLinkedList.HEAD_POSITION && this.internalPos != ObjectLinkedList.TAIL_POSITION) { //this is the next position in the normal iteration direction, so we must go back one step final int nextPos = removeAtPosNoCheck(this.internalPos); this.internalPos = ((int) (this.pointers[nextPos] >> 32)); this.internalIndex--; //update cursor this.cursor.value = this.buffer[this.internalPos]; //index is decremented this.cursor.index = this.internalIndex; } return this; } } /** * * Request a new iterator. The iterator points to "head", such as ValueIterator.gotoNext() * is the first element of the list. * * Important note: java.util.Iterator methods are error-prone, and only there for compatibility and enhanced for loop usage: *
     * for (ObjectCursor c : container) {
     *      System.out.println("index=" + c.index + " value=" + c.value);
     *    }
     * 
* Prefer the specialized methods instead : *
     * ValueIterator it = list.iterator();
     * while (!it.isTail())
     * {
     *     final ObjectCursor c = it.gotoNext();
     *     System.out.println("buffer index="
     *         + c.index + " value=" + c.value);
     * }
     * 
     * // release the iterator at the end !
     * it.release()
     * 
*
* @see ValueIterator#isHead() */ @Override public ValueIterator iterator() { //return new ValueIterator(); return this.valueIteratorPool.borrow(); } /** * Returns a cursor over the values of this list (in tail to head order). * The iterator points to the "head", such as DescendingValueIterator.gotoNext() * is the last element of the list (since it is a "reversed" iteration). * The iterator is implemented as a cursor and it returns the same cursor instance * on every call to {@link Iterator#next()} (to avoid boxing of primitive types). To * read the current value (or index in the deque's buffer) use the cursor's public * fields. An example is shown below. * * Important note: java.util.Iterator methods are error-prone, and only there for compatibility. Use * the specialized methods instead : * *
     * DescendingValueIterator it = list.descendingIterator();
     * while (!it.isTail())
     * {
     *     final ObjectCursor c = it.gotoNext();
     *     System.out.println("buffer index="
     *         + c.index + " value=" + c.value);
     * }
     * 
     * // release the iterator at the end !
     * it.release()
     * 
*
* @see ValueIterator#isHead() */ @Override public DescendingValueIterator descendingIterator() { //return new DescendingValueIterator(); return this.descendingValueIteratorPool.borrow(); } /** * {@inheritDoc} */ @Override public > T forEach(final T procedure) { final long[] pointers = this.beforeAfterPointers; final KType[] buffer = this.buffer; int currentPos = ((int) (pointers[ObjectLinkedList.HEAD_POSITION] & 0x00000000FFFFFFFFL)); while (currentPos != ObjectLinkedList.TAIL_POSITION) { procedure.apply(buffer[currentPos]); currentPos = ((int) (pointers[currentPos] & 0x00000000FFFFFFFFL)); } //end while return procedure; } /** * {@inheritDoc} */ @Override public > T forEach(final T predicate) { final long[] pointers = this.beforeAfterPointers; final KType[] buffer = this.buffer; int currentPos = ((int) (pointers[ObjectLinkedList.HEAD_POSITION] & 0x00000000FFFFFFFFL)); while (currentPos != ObjectLinkedList.TAIL_POSITION) { if (!predicate.apply(buffer[currentPos])) { break; } currentPos = ((int) (pointers[currentPos] & 0x00000000FFFFFFFFL)); } //end while return predicate; } /** * {@inheritDoc} */ @Override public > T descendingForEach(final T procedure) { final long[] pointers = this.beforeAfterPointers; final KType[] buffer = this.buffer; int currentPos = ((int) (pointers[ObjectLinkedList.TAIL_POSITION] >> 32)); while (currentPos != ObjectLinkedList.HEAD_POSITION) { procedure.apply(buffer[currentPos]); currentPos = ((int) (pointers[currentPos] >> 32)); } //end while return procedure; } /** * {@inheritDoc} */ @Override public > T descendingForEach(final T predicate) { final long[] pointers = this.beforeAfterPointers; final KType[] buffer = this.buffer; int currentPos = ((int) (pointers[ObjectLinkedList.TAIL_POSITION] >> 32)); while (currentPos != ObjectLinkedList.HEAD_POSITION) { if (!predicate.apply(buffer[currentPos])) { break; } currentPos = ((int) (pointers[currentPos] >> 32)); } //end while return predicate; } /** * {@inheritDoc} */ @Override public int removeAll(final ObjectPredicate predicate) { final KType[] buffer = this.buffer; int deleted = 0; //real elements starts in position 2. int pos = 2; //directly iterate the buffer, so out of order. while (pos < this.elementsCount) { if (predicate.apply(buffer[pos])) { //each time a pos is removed, pos itself is patched with the last element, //so continue to test the same position. removeAtPosNoCheck(pos); deleted++; } else { pos++; } } //end while return deleted; } /** * Returns a new object of this class with no need to declare generic type (shortcut * instead of using a constructor). */ public static/* */ /* */ ObjectLinkedList newInstance() { return new ObjectLinkedList(); } /** * Returns a new object of this class with no need to declare generic type (shortcut * instead of using a constructor). */ public static/* */ /* */ ObjectLinkedList newInstanceWithCapacity(final int initialCapacity) { return new ObjectLinkedList(initialCapacity); } /** * Create a list from a variable number of arguments or an array of KType. * The elements are copied from the argument to the internal buffer. */ public static/* */ /* */ ObjectLinkedList from(final KType... elements) { final ObjectLinkedList list = new ObjectLinkedList(elements.length); list.add(elements); return list; } /** * Create a list from elements of another container. */ public static/* */ /* */ ObjectLinkedList from(final ObjectContainer container) { return new ObjectLinkedList(container); } /** * In-place sort the list from [beginIndex, endIndex[ * by natural ordering (smaller first) *

* WARNING: This method runs in O(n*n*log(n)). Consider yourself warned. *

* @param beginIndex the start index to be sorted * @param endIndex the end index to be sorted (excluded) */ /** * In-place sort the list from [beginIndex, endIndex[ * using a Comparator *

* This routine uses Dual-pivot Quicksort, from [Yaroslavskiy 2009] , so is NOT stable. *

*

* WARNING: This method runs in O(n*n*log(n)). Consider yourself warned. *

* @param beginIndex the start index to be sorted * @param endIndex the end index to be sorted (excluded) */ public void sort( final int beginIndex, final int endIndex, final Comparator comp) { assert endIndex <= size(); if (endIndex - beginIndex > 1) { ObjectSort.quicksort(this, beginIndex, endIndex, comp); } } /** * In-place sort the whole list by natural ordering (smaller first) *

* This routine uses Dual-pivot Quicksort, from [Yaroslavskiy 2009] *

* @param beginIndex * @param endIndex */ //////////////////////////// /** * In-place sort the whole list * using a Comparator *

* This routine uses Dual-pivot Quicksort, from [Yaroslavskiy 2009] , so is NOT stable. *

*/ public void sort( final Comparator comp) { if (this.elementsCount > 3) { final int elementsCount = this.elementsCount; final long[] pointers = this.beforeAfterPointers; ObjectSort.quicksort(this.buffer, 2, elementsCount, comp); //rebuild nodes, in order //a) rebuild head/tail //ties HEAD to the first element, and first element to HEAD pointers[ObjectLinkedList.HEAD_POSITION] = (((long) ObjectLinkedList.HEAD_POSITION << 32) | 2); pointers[2] = (((long) ObjectLinkedList.HEAD_POSITION << 32) | 3); for (int pos = 3; pos < elementsCount - 1; pos++) { pointers[pos] = (((long) pos - 1 << 32) | pos + 1); } //ties the last element to tail, and tail to last element pointers[elementsCount - 1] = (((long) elementsCount - 2 << 32) | ObjectLinkedList.TAIL_POSITION); pointers[ObjectLinkedList.TAIL_POSITION] = (((long) elementsCount - 1 << 32) | ObjectLinkedList.TAIL_POSITION); } } @Override public void addFirst(final KType e1) { ensureBufferSpace(1); insertAfterPosNoCheck(e1, ObjectLinkedList.HEAD_POSITION); } /** * Inserts all elements from the given container to the front of this list. * * @return Returns the number of elements actually added as a result of this * call. */ public int addFirst(final ObjectContainer container) { return addFirst((Iterable>) container); } /** * Vararg-signature method for adding elements at the front of this deque. * *

This method is handy, but costly if used in tight loops (anonymous * array passing)

*/ public void addFirst(final KType... elements) { ensureBufferSpace(elements.length); // For now, naive loop. for (int i = 0; i < elements.length; i++) { insertAfterPosNoCheck(elements[i], ObjectLinkedList.HEAD_POSITION); } } /** * Inserts all elements from the given iterable to the front of this list. * * @return Returns the number of elements actually added as a result of this call. */ public int addFirst(final Iterable> iterable) { int size = 0; for (final ObjectCursor cursor : iterable) { ensureBufferSpace(1); insertAfterPosNoCheck(cursor.value, ObjectLinkedList.HEAD_POSITION); size++; } return size; } @Override public void addLast(final KType e1) { ensureBufferSpace(1); insertAfterPosNoCheck(e1, ((int) (this.beforeAfterPointers[ObjectLinkedList.TAIL_POSITION] >> 32))); } /** * Inserts all elements from the given container to the end of this list. * * @return Returns the number of elements actually added as a result of this * call. */ public int addLast(final ObjectContainer container) { return addLast((Iterable>) container); } /** * Inserts all elements from the given iterable to the end of this list. * * @return Returns the number of elements actually added as a result of this call. */ public int addLast(final Iterable> iterable) { int size = 0; for (final ObjectCursor cursor : iterable) { ensureBufferSpace(1); insertAfterPosNoCheck(cursor.value, ((int) (this.beforeAfterPointers[ObjectLinkedList.TAIL_POSITION] >> 32))); size++; } return size; } @Override public KType removeFirst() { assert size() > 0; final int removedPos = ((int) (this.beforeAfterPointers[ObjectLinkedList.HEAD_POSITION] & 0x00000000FFFFFFFFL)); final KType elem = this.buffer[removedPos]; removeAtPosNoCheck(removedPos); return elem; } @Override public KType removeLast() { assert size() > 0; final int removedPos = ((int) (this.beforeAfterPointers[ObjectLinkedList.TAIL_POSITION] >> 32)); final KType elem = this.buffer[removedPos]; removeAtPosNoCheck(removedPos); return elem; } @Override public KType getFirst() { assert size() > 0; return this.buffer[((int) (this.beforeAfterPointers[ObjectLinkedList.HEAD_POSITION] & 0x00000000FFFFFFFFL))]; } @Override public KType getLast() { assert size() > 0; return this.buffer[((int) (this.beforeAfterPointers[ObjectLinkedList.TAIL_POSITION] >> 32))]; } }