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

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

package com.carrotsearch.hppcrt.lists;

import java.util.*;

import com.carrotsearch.hppcrt.*;
import com.carrotsearch.hppcrt.cursors.*;
import com.carrotsearch.hppcrt.hash.BitMixer;
import com.carrotsearch.hppcrt.lists.ObjectLinkedList.ValueIterator;
import com.carrotsearch.hppcrt.predicates.*;
import com.carrotsearch.hppcrt.procedures.*;
import com.carrotsearch.hppcrt.sorting.*;
import com.carrotsearch.hppcrt.strategies.*;

  
/**
 * An array-backed deque (double-ended queue)  of Objects. A single array is used to store and
 * manipulate all elements. Reallocations are governed by a {@link ArraySizingStrategy}
 * and may be expensive if they move around really large chunks of memory.
 * This dequeue is also a ObjectIndexedContainer, where index 0 is the head of the queue, and
 * size() - 1 index is the last element.
 * A brief comparison of the API against the Java Collections framework:
 * 
 * 
 * 
 * 
 * 
 * 
 * 
 * 
 * 
 * 
 * 
 * 
 * 
 * 
 * 
 * 
 * 
 * 
 * 
 * 
 * 
Java Collections ArrayDeque and HPPC {@link ObjectArrayDeque}, related methods.
{@linkplain ArrayDeque java.util.ArrayDeque}{@link ObjectArrayDeque}
addFirst addFirst
addLast addLast
removeFirst removeLast
getFirst getFirst
getLast getLast
removeFirstOccurrence, * removeLastOccurrence * removeFirstOccurrence, * removeLastOccurrence *
size size
Object[] toArray()Object[] toArray()
iterator {@linkplain #iterator cursor over values}
other methods inherited from Stack, Queuenot implemented
*/ @javax.annotation.Generated( date = "2016-01-30T23:09:30+0100", value = "KTypeArrayDeque.java") public class ObjectArrayDeque extends AbstractObjectCollection implements ObjectDeque, ObjectIndexedContainer, Cloneable { /** * Internal array for storing elements. * *

* Direct deque iteration from head to tail: iterate buffer[i % buffer.length] for i in [this.head; this.head + size()[ *

*/ public Object[] buffer; /** * The index of the element at the head of the deque or an * arbitrary number equal to tail if the deque is empty. */ public int head; /** * The index at which the next element would be added to the tail * of the deque. (this is a valid index in buffer !) */ public int tail; /** * Buffer resizing strategy. */ protected final ArraySizingStrategy resizer; /** * internal pool of DescendingValueIterator (must be created in constructor) */ protected final IteratorPool, DescendingValueIterator> descendingValueIteratorPool; /** * internal pool of ValueIterator (must be created in constructor) */ protected final IteratorPool, ValueIterator> valueIteratorPool; /** * Default constructor. */ public ObjectArrayDeque() { this(Containers.DEFAULT_EXPECTED_ELEMENTS); } /** * Create with default sizing strategy and the given initial capacity. * * @see BoundedProportionalArraySizingStrategy */ public ObjectArrayDeque(final int initialCapacity) { this(initialCapacity, new BoundedProportionalArraySizingStrategy()); } /** * Create with a custom buffer resizing strategy. */ public ObjectArrayDeque(final int initialCapacity, final ArraySizingStrategy resizer) { assert resizer != null; this.resizer = resizer; //Allocate to capacity ensureBufferSpace(Math.max(Containers.DEFAULT_EXPECTED_ELEMENTS, initialCapacity)); this.valueIteratorPool = new IteratorPool, ValueIterator>(new ObjectFactory() { @Override public ValueIterator create() { return new ValueIterator(); } @Override public void initialize(final ValueIterator obj) { obj.cursor.index = (((ObjectArrayDeque.this.head) >= 1) ? (ObjectArrayDeque.this.head) - 1 : (ObjectArrayDeque.this.buffer.length) - 1); obj.remaining = ObjectArrayDeque.this.size(); } @Override public void reset(final ValueIterator obj) { obj.cursor.value = null; } }); this.descendingValueIteratorPool = new IteratorPool, DescendingValueIterator>( new ObjectFactory() { @Override public DescendingValueIterator create() { return new DescendingValueIterator(); } @Override public void initialize(final DescendingValueIterator obj) { obj.cursor.index = ObjectArrayDeque.this.tail; obj.remaining = ObjectArrayDeque.this.size(); } @Override public void reset(final DescendingValueIterator obj) { obj.cursor.value = null; } }); } /** * Creates a new deque from elements of another container, appending them * at the end of this deque. */ public ObjectArrayDeque(final ObjectContainer container) { this(container.size()); addLast(container); } /** * {@inheritDoc} */ @Override public void addFirst(final KType e1) { int h = (((this.head) >= 1) ? (this.head) - 1 : (this.buffer.length) - 1); if (h == this.tail) { ensureBufferSpace(1); h = (((this.head) >= 1) ? (this.head) - 1 : (this.buffer.length) - 1); } this.buffer[this.head = h] = e1; } /** * 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++) { addFirst(elements[i]); } } /** * Inserts all elements from the given container to the front of this deque. * * @return Returns the number of elements actually added as a result of this * call. */ public int addFirst(final ObjectContainer container) { return addFirst((Iterable>) container); } /** * Inserts all elements from the given iterable to the front of this deque. * * @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) { addFirst(cursor.value); size++; } return size; } /** * {@inheritDoc} */ @Override public void addLast(final KType e1) { int t = (((this.tail) + 1 == (this.buffer.length)) ? 0 : (this.tail) + 1); if (this.head == t) { ensureBufferSpace(1); t = (((this.tail) + 1 == (this.buffer.length)) ? 0 : (this.tail) + 1); } this.buffer[this.tail] = e1; this.tail = t; } /** * Vararg-signature method for adding elements at the end of this deque. * *

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

*/ public void addLast(final KType... elements) { ensureBufferSpace(elements.length); // For now, naive loop. for (int i = 0; i < elements.length; i++) { addLast(elements[i]); } } /** * Inserts all elements from the given container to the end of this deque. * * @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 deque. * * @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) { addLast(cursor.value); size++; } return size; } /** * {@inheritDoc} */ @Override public KType removeFirst() { assert size() > 0 : "The deque is empty."; final KType result = ((KType)(this.buffer[this.head])); this.buffer[this.head] = (null); this.head = (((this.head) + 1 == (this.buffer.length)) ? 0 : (this.head) + 1); return result; } /** * {@inheritDoc} */ @Override public KType removeLast() { assert size() > 0 : "The deque is empty."; this.tail = (((this.tail) >= 1) ? (this.tail) - 1 : (this.buffer.length) - 1); final KType result = ((KType)(this.buffer[this.tail])); this.buffer[this.tail] = (null); return result; } /** * {@inheritDoc} */ @Override public KType getFirst() { assert size() > 0 : "The deque is empty."; return ((KType)(this.buffer[this.head])); } /** * {@inheritDoc} */ @Override public KType getLast() { assert size() > 0 : "The deque is empty."; return ((KType)(this.buffer[(((this.tail) >= 1) ? (this.tail) - 1 : (this.buffer.length) - 1)])); } /** * {@inheritDoc} * The returned position is relative to the head, * i.e w.r.t the {@link ObjectIndexedContainer}, index 0 is the head of the queue, size() - 1 is the last element position. */ @Override public int removeFirst(final KType e1) { int pos = -1; final int index = bufferIndexOf(e1); if (index >= 0) { pos = bufferIndexToPosition(index); removeBufferIndicesRange(index, (((index) + 1 == (this.buffer.length)) ? 0 : (index) + 1)); } return pos; } /** * Return the index of the first element equal to * e1. The index points to the {@link #buffer} array. * * @param e1 The element to look for. * @return Returns the index in {@link #buffer} of the first element equal to e1 * or -1 if not found. */ public int bufferIndexOf(final KType e1) { final int last = this.tail; final int bufLen = this.buffer.length; final KType[] buffer = ((KType[])(this.buffer)); for (int i = this.head; i != last; i = (((i) + 1 == (bufLen)) ? 0 : (i) + 1)) { if (((e1) == null ? (buffer[i]) == null : (e1).equals((buffer[i])))) { return i; } } return -1; } /** * {@inheritDoc} * The returned position is relative to the head, * i.e w.r.t the {@link ObjectIndexedContainer}, index 0 is the head of the queue, size() - 1 is the last element position. */ @Override public int removeLast(final KType e1) { int pos = -1; final int index = lastBufferIndexOf(e1); if (index >= 0) { pos = bufferIndexToPosition(index); removeBufferIndicesRange(index, (((index) + 1 == (this.buffer.length)) ? 0 : (index) + 1)); } return pos; } /** * Return the index of the last element equal to * e1. The index points to the {@link #buffer} array. * * @param e1 The element to look for. * @return Returns the index in {@link #buffer} of the first element equal to e1 * or -1 if not found. */ public int lastBufferIndexOf(final KType e1) { final int bufLen = this.buffer.length; final int last = (((this.head) >= 1) ? (this.head) - 1 : (bufLen) - 1); final KType[] buffer = ((KType[])(this.buffer)); for (int i = (((this.tail) >= 1) ? (this.tail) - 1 : (bufLen) - 1); i != last; i = (((i) >= 1) ? (i) - 1 : (bufLen) - 1)) { if (((e1) == null ? (buffer[i]) == null : (e1).equals((buffer[i])))) { return i; } } return -1; } /** * ObjectIndexedContainer methods */ /** * {@inheritDoc} * The returned position is relative to the head, * i.e w.r.t the {@link ObjectIndexedContainer}, index 0 is the head of the queue, size() - 1 is the last element position. */ @Override public int indexOf(final KType e1) { return bufferIndexToPosition(bufferIndexOf(e1)); } /** * {@inheritDoc} * The returned position is relative to the head, * i.e w.r.t the {@link ObjectIndexedContainer}, index 0 is the head of the queue, size() - 1 is the last element position. */ @Override public int lastIndexOf(final KType e1) { return bufferIndexToPosition(lastBufferIndexOf(e1)); } /** * {@inheritDoc} */ @Override public int removeAll(final KType e1) { int removed = 0; final int last = this.tail; final int bufLen = this.buffer.length; final KType[] buffer = ((KType[])(this.buffer)); int from, to; for (from = to = this.head; from != last; from = (((from) + 1 == (bufLen)) ? 0 : (from) + 1)) { if (((e1) == null ? (buffer[from]) == null : (e1).equals((buffer[from])))) { buffer[from] = (null); removed++; continue; } if (to != from) { buffer[to] = buffer[from]; buffer[from] = (null); } to = (((to) + 1 == (bufLen)) ? 0 : (to) + 1); } this.tail = to; return removed; } /** * {@inheritDoc} */ @Override public int size() { if (this.head <= this.tail) { return this.tail - this.head; } return (this.tail - this.head + this.buffer.length); } /** * {@inheritDoc} */ @Override public int capacity() { //because there is always an empty slot in the buffer return this.buffer.length - 1; } /** * {@inheritDoc} *

The internal array buffers are not released as a result of this call.

*/ @Override public void clear() { if (this.head < this.tail) { ObjectArrays.blankArray(this.buffer, this.head, this.tail); } else { ObjectArrays.blankArray(this.buffer, 0, this.tail); ObjectArrays.blankArray(this.buffer, this.head, this.buffer.length); } this.head = this.tail = 0; } /** * Compact the internal buffer to prepare sorting * Beware, this changes the relative order of elements, so is only useful to * not-stable sorts while sorting the WHOLE buffer ! */ private void compactBeforeSorting() { if (this.head > this.tail) { final int size = size(); final int hole = this.head - this.tail; //pack the separated chunk to the beginning of the buffer System.arraycopy(this.buffer, this.head, this.buffer, this.tail, this.buffer.length - this.head); //reset of the positions this.head = 0; this.tail = size; //for GC sake, reset hole elements now at the end of buffer ObjectArrays.blankArray(this.buffer, this.tail, this.tail + hole); } } /** * Release internal buffers of this deque and reallocate the smallest buffer possible. */ public void release() { this.head = this.tail = 0; this.buffer = ((KType[])new Object[(Containers.DEFAULT_EXPECTED_ELEMENTS)]); } /** * Ensures the internal buffer has enough free slots to store * expectedAdditions. Increases internal buffer size if needed. */ @SuppressWarnings("boxing") protected void ensureBufferSpace(final int expectedAdditions) { final int bufferLen = (this.buffer == null ? 0 : this.buffer.length); final int elementsCount = (this.buffer == null ? 0 : size()); // +1 because there is always one empty slot in a deque. if (elementsCount + 1 > bufferLen - expectedAdditions) { int newSize = this.resizer.grow(bufferLen, elementsCount, expectedAdditions); if (this.buffer == null) { //first allocation, reserve an additional slot (tail is always a valid index in buffer) newSize++; } try { final KType[] newBuffer = ((KType[])new Object[(newSize)]); if (bufferLen > 0) { toArray(newBuffer); this.tail = elementsCount; this.head = 0; } this.buffer = newBuffer; } catch (final OutOfMemoryError e) { throw new BufferAllocationException( "Not enough memory to allocate buffers to grow from %d -> %d elements", e, bufferLen, newSize); } } } /** * Copies elements of this deque to an array. The content of the target * array is filled from index 0 (head of the queue) to index size() - 1 * (tail of the queue). * * @param target The target array must be large enough to hold all elements. * @return Returns the target argument for chaining. */ @Override public KType[] toArray(final KType[] target) { assert target.length >= size() : "Target array must be >= " + size(); if (this.head < this.tail) { // The contents is not wrapped around. Just copy. System.arraycopy(this.buffer, this.head, target, 0, size()); } else if (this.head > this.tail) { // The contents is split. Merge elements from the following indexes: // [head...buffer.length - 1][0, tail - 1] final int rightCount = this.buffer.length - this.head; System.arraycopy(this.buffer, this.head, target, 0, rightCount); System.arraycopy(this.buffer, 0, target, rightCount, this.tail); } return target; } /** * Clone this object. The returned clone will reuse the same array resizing strategy. */ @Override public ObjectArrayDeque clone() { //placeholder container final ObjectArrayDeque cloned = new ObjectArrayDeque(Containers.DEFAULT_EXPECTED_ELEMENTS, this.resizer); //copy the full buffer cloned.buffer = this.buffer.clone(); cloned.head = this.head; cloned.tail = this.tail; return cloned; } /** * An iterator implementation for {@link ObjectArrayDeque#iterator}. */ public final class ValueIterator extends AbstractIterator> { public final ObjectCursor cursor; private int remaining; public ValueIterator() { this.cursor = new ObjectCursor(); this.cursor.index = (((ObjectArrayDeque.this.head) >= 1) ? (ObjectArrayDeque.this.head) - 1 : (ObjectArrayDeque.this.buffer.length) - 1); this.remaining = ObjectArrayDeque.this.size(); } @Override protected ObjectCursor fetch() { if (this.remaining == 0) { return done(); } this.remaining--; this.cursor.value = ((KType)(ObjectArrayDeque.this.buffer[this.cursor.index = (((this.cursor.index) + 1 == (ObjectArrayDeque.this.buffer.length)) ? 0 : (this.cursor.index) + 1)])); return this.cursor; } } /** * An iterator implementation for {@link ObjectArrayDeque#descendingIterator()}. */ public final class DescendingValueIterator extends AbstractIterator> { public final ObjectCursor cursor; private int remaining; public DescendingValueIterator() { this.cursor = new ObjectCursor(); this.cursor.index = ObjectArrayDeque.this.tail; this.remaining = ObjectArrayDeque.this.size(); } @Override protected ObjectCursor fetch() { if (this.remaining == 0) { return done(); } this.remaining--; this.cursor.value = ((KType)(ObjectArrayDeque.this.buffer[this.cursor.index = (((this.cursor.index) >= 1) ? (this.cursor.index) - 1 : (ObjectArrayDeque.this.buffer.length) - 1)])); return this.cursor; } } /** * Returns an iterator over the values of this deque (in head to tail order). 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 {@link #buffer}, use the cursor's public * fields. An example is shown below. * *
     * for (IntValueCursor c : intDeque)
     * {
     *     System.out.println("buffer index="
     *         + c.index + " value=" + c.value);
     * }
     * 
*/ @Override public ValueIterator iterator() { //return new ValueIterator(); return this.valueIteratorPool.borrow(); } /** * Returns an iterator over the values of this deque (in tail to head order). 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 {@link #buffer}, use the cursor's public * fields. An example is shown below. * *
     * for (Iterator i = intDeque.descendingIterator(); i.hasNext(); )
     * {
     *   final IntCursor c = i.next();
     *     System.out.println("buffer index="
     *         + c.index + " value=" + c.value);
     * }
     * 
* */ @Override public DescendingValueIterator descendingIterator() { //return new DescendingValueIterator(); return this.descendingValueIteratorPool.borrow(); } /** * {@inheritDoc} */ @Override public > T forEach(final T procedure) { internalForEach(procedure, this.head, this.tail); return procedure; } /** * {@inheritDoc} */ @Override public > T forEach(final T procedure, final int fromIndex, final int toIndex) { checkRangeBounds(fromIndex, toIndex); if (fromIndex == toIndex) { return procedure; //nothing to do } final int bufferPositionStart = indexToBufferPosition(fromIndex); final int endBufferPosInclusive = indexToBufferPosition(toIndex - 1); //must be a valid index internalForEach(procedure, bufferPositionStart, (((endBufferPosInclusive) + 1 == (this.buffer.length)) ? 0 : (endBufferPosInclusive) + 1)); return procedure; } /** * Applies procedure to a slice of the deque, * fromIndexBuffer, inclusive, to toIndexBuffer, * exclusive, indices are in {@link #buffer} array. */ private void internalForEach(final ObjectProcedure procedure, final int fromIndexBuffer, final int toIndexBuffer) { final KType[] buffer = ((KType[])(this.buffer)); for (int i = fromIndexBuffer; i != toIndexBuffer; i = (((i) + 1 == (buffer.length)) ? 0 : (i) + 1)) { procedure.apply(buffer[i]); } } /** * {@inheritDoc} */ @Override public > T forEach(final T predicate) { internalForEach(predicate, this.head, this.tail); return predicate; } /** * {@inheritDoc} */ @Override public > T forEach(final T predicate, final int fromIndex, final int toIndex) { checkRangeBounds(fromIndex, toIndex); if (fromIndex == toIndex) { return predicate; //nothing to do } final int bufferPositionStart = indexToBufferPosition(fromIndex); final int endBufferPosInclusive = indexToBufferPosition(toIndex - 1); //must be a valid index internalForEach(predicate, bufferPositionStart, (((endBufferPosInclusive) + 1 == (this.buffer.length)) ? 0 : (endBufferPosInclusive) + 1)); return predicate; } /** * Applies predicate to a slice of the deque, * fromIndexBuffer, inclusive, to toIndexBuffer, * exclusive, indices are in {@link #buffer} array. */ private void internalForEach(final ObjectPredicate predicate, final int fromIndexBuffer, final int toIndexBuffer) { final KType[] buffer = ((KType[])(this.buffer)); for (int i = fromIndexBuffer; i != toIndexBuffer; i = (((i) + 1 == (buffer.length)) ? 0 : (i) + 1)) { if (!predicate.apply(buffer[i])) { break; } } } /** * Applies procedure to all elements of this deque, tail to head. */ @Override public > T descendingForEach(final T procedure) { descendingForEach(procedure, this.head, this.tail); return procedure; } /** * Applies procedure to a slice of the deque, * toIndex, exclusive, down to fromIndex, inclusive. */ private void descendingForEach(final ObjectProcedure procedure, final int fromIndex, final int toIndex) { if (fromIndex == toIndex) { return; } final KType[] buffer = ((KType[])(this.buffer)); int i = toIndex; do { i = (((i) >= 1) ? (i) - 1 : (buffer.length) - 1); procedure.apply(buffer[i]); } while (i != fromIndex); } /** * {@inheritDoc} */ @Override public > T descendingForEach(final T predicate) { descendingForEach(predicate, this.head, this.tail); return predicate; } /** * Applies predicate to a slice of the deque, * toIndex, exclusive, down to fromIndex, inclusive * or until the predicate returns false. * Indices are in {@link #buffer} array. */ private void descendingForEach(final ObjectPredicate predicate, final int fromIndex, final int toIndex) { if (fromIndex == toIndex) { return; } final KType[] buffer = ((KType[])(this.buffer)); int i = toIndex; do { i = (((i) >= 1) ? (i) - 1 : (buffer.length) - 1); if (!predicate.apply(buffer[i])) { break; } } while (i != fromIndex); } /** * {@inheritDoc} */ @Override public int removeAll(final ObjectPredicate predicate) { int removed = 0; final int last = this.tail; final int bufLen = this.buffer.length; final KType[] buffer = ((KType[])(this.buffer)); int from, to; from = to = this.head; try { for (from = to = this.head; from != last; from = (((from) + 1 == (bufLen)) ? 0 : (from) + 1)) { if (predicate.apply(buffer[from])) { buffer[from] = (null); removed++; continue; } if (to != from) { buffer[to] = buffer[from]; buffer[from] = (null); } to = (((to) + 1 == (bufLen)) ? 0 : (to) + 1); } } finally { // Keep the deque in consistent state even if the predicate throws an exception. for (; from != last; from = (((from) + 1 == (bufLen)) ? 0 : (from) + 1)) { if (to != from) { buffer[to] = buffer[from]; buffer[from] = (null); } to = (((to) + 1 == (bufLen)) ? 0 : (to) + 1); } this.tail = to; } return removed; } /** * {@inheritDoc} */ @Override public boolean contains(final KType e) { final int fromIndex = this.head; final int toIndex = this.tail; final KType[] buffer = ((KType[])(this.buffer)); for (int i = fromIndex; i != toIndex; i = (((i) + 1 == (buffer.length)) ? 0 : (i) + 1)) { if (((e) == null ? (buffer[i]) == null : (e).equals((buffer[i])))) { return true; } } return false; } /** * {@inheritDoc} */ @Override public int hashCode() { int h = 1; final int fromIndex = this.head; final int toIndex = this.tail; final KType[] buffer = ((KType[])(this.buffer)); for (int i = fromIndex; i != toIndex; i = (((i) + 1 == (buffer.length)) ? 0 : (i) + 1)) { h = 31 * h + BitMixer.mix(buffer[i]); } return h; } /** * {@inheritDoc} */ @Override @SuppressWarnings("unchecked") public boolean equals(final Object obj) { if (obj != null) { if (obj == this) { return true; } if (obj instanceof ObjectLinkedList) { //Access by index is slow, iterate by iterator when the other is a linked list final ObjectLinkedList other = (ObjectLinkedList) obj; if (other.size() != this.size()) { return false; } final ValueIterator it = this.iterator(); final ObjectLinkedList.ValueIterator itOther = (ObjectLinkedList.ValueIterator) other.iterator(); while (it.hasNext()) { final KType myVal = it.next().value; final KType otherVal = itOther.next().value; if (!((myVal) == null ? (otherVal) == null : (myVal).equals((otherVal)))) { //recycle it.release(); itOther.release(); return false; } } //end while itOther.release(); return true; } else if (obj instanceof ObjectIndexedContainer) { //we can compare with any ObjectIndexedContainer : final ObjectIndexedContainer other = (ObjectIndexedContainer) obj; return other.size() == this.size() && allIndexesEqual(this, (ObjectIndexedContainer) other, this.size()); } } return false; } /** * Compare index-aligned ObjectIndexedContainer objects */ private boolean allIndexesEqual(final ObjectIndexedContainer b1, final ObjectIndexedContainer b2, final int length) { for (int i = 0; i < length; i++) { final KType o1 = b1.get(i); final KType o2 = b2.get(i); if (!((o1) == null ? (o2) == null : (o1).equals((o2)))) { return false; } } return true; } /** * Returns a new object of this class with no need to declare generic type (shortcut * instead of using a constructor). */ public static/* */ /* */ ObjectArrayDeque newInstance() { return new ObjectArrayDeque(); } /** * Returns a new object of this class with no need to declare generic type (shortcut * instead of using a constructor). */ public static/* */ /* */ ObjectArrayDeque newInstance(final int initialCapacity) { return new ObjectArrayDeque(initialCapacity); } /** * Create a new deque by pushing a variable number of arguments to the end of it. */ public static/* */ /* */ ObjectArrayDeque from(final KType... elements) { final ObjectArrayDeque coll = new ObjectArrayDeque(elements.length); coll.addLast(elements); return coll; } /** * Create a new deque by pushing a variable number of arguments to the end of it. */ public static/* */ /* */ ObjectArrayDeque from(final ObjectContainer container) { return new ObjectArrayDeque(container); } //////////////////////////// /** * In-place sort the dequeue from [beginIndex, endIndex[ * by natural ordering (smaller first) * @param beginIndex the start index to be sorted * @param endIndex the end index to be sorted (excluded) *

* This sort is NOT stable. *

* @throws ClassCastException if the deque contains elements that are not mutually Comparable. */ public void sort(final int beginIndex, final int endIndex) { checkRangeBounds(beginIndex, endIndex); if (beginIndex == endIndex) { return; //nothing to do } //Fast path : if the actual indices matching [beginIndex; endIndex[ //in the underlying buffer are in increasing order (means there is no folding of buffer in the interval), // use quicksort array version directly. final int bufferPosStart = indexToBufferPosition(beginIndex); final int bufferPosEndInclusive = indexToBufferPosition(endIndex - 1); //must be a valid index if (bufferPosEndInclusive > bufferPosStart) { ObjectSort.quicksort(this.buffer, bufferPosStart, bufferPosEndInclusive + 1); } else { //Use the slower ObjectIndexedContainer sort ObjectSort.quicksort(this, beginIndex, endIndex); } } /** * In-place sort the dequeue from [beginIndex, endIndex[ * using a Comparator *

* This sort is NOT stable. *

* @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) { checkRangeBounds(beginIndex, endIndex); if (beginIndex == endIndex) { return; //nothing to do } //Fast path : if the actual indices matching [beginIndex; endIndex[ //in the underlying buffer are in increasing order (means there is no folding of buffer in the interval), // use quicksort array version directly. final int bufferPosStart = indexToBufferPosition(beginIndex); final int bufferPosEndInclusive = indexToBufferPosition(endIndex - 1); //must be valid indices if (bufferPosEndInclusive > bufferPosStart) { ObjectSort.quicksort(((KType[])(this.buffer)), bufferPosStart, bufferPosEndInclusive + 1, comp); } else { //Use the slower ObjectIndexedContainer sort ObjectSort.quicksort(this, beginIndex, endIndex, comp); } } /** * In-place sort the whole dequeue by natural ordering (smaller first) *

* This sort is NOT stable. *

* @throws ClassCastException if the deque contains elements that are not mutually Comparable. */ public void sort() { if (size() > 1) { compactBeforeSorting(); ObjectSort.quicksort(this.buffer, this.head, this.tail); } } //////////////////////////// /** * In-place sort the whole dequeue * using a Comparator *

* This sort is NOT stable. *

*/ public void sort( final Comparator comp) { if (size() > 1) { compactBeforeSorting(); ObjectSort.quicksort(((KType[])(this.buffer)), this.head, this.tail, comp); } } /** * ObjectIndexedContainer methods */ /** * {@inheritDoc} */ @Override public void add(final KType e1) { addLast(e1); } /** * This operation is not supported on array deques, throwing UnsupportedOperationException. * @throws UnsupportedOperationException */ @Override public void insert(final int index, final KType e1) { throw new UnsupportedOperationException( "insert(final int index, final KType e1) operation is not supported on KTypeArrayDeque"); } /** * {@inheritDoc} * The position is relative to the head, * i.e w.r.t the {@link ObjectIndexedContainer}, index 0 is the head of the queue, size() - 1 is the last element position. */ @Override public KType set(final int index, final KType e1) { final int indexInBuffer = indexToBufferPosition(index); final KType previous = ((KType)(this.buffer[indexInBuffer])); this.buffer[indexInBuffer] = e1; return previous; } /** * {@inheritDoc} * The position is relative to the head, * i.e w.r.t the {@link ObjectIndexedContainer}, index 0 is the head of the queue, size() - 1 is the last element position. */ @Override public KType get(final int index) { return ((KType)(this.buffer[indexToBufferPosition(index)])); } /** * {@inheritDoc} * The position is relative to the head, * i.e w.r.t the {@link ObjectIndexedContainer}, index 0 is the head of the queue, size() - 1 is the last element position. */ @Override public KType remove(final int index) { final int indexInBuffer = indexToBufferPosition(index); final KType previous = ((KType)(this.buffer[indexInBuffer])); removeBufferIndicesRange(indexInBuffer, (((indexInBuffer) + 1 == (this.buffer.length)) ? 0 : (indexInBuffer) + 1)); return previous; } /** * Remove all elements in [fromBufferIndex; toBufferIndex[ indices in {@link #buffer}. * @param fromBufferIndex * @param toBufferIndex */ private void removeBufferIndicesRange(final int fromBufferIndex, final int toBufferIndex) { final int bufLen = this.buffer.length; final KType[] buffer = ((KType[])(this.buffer)); if (fromBufferIndex == toBufferIndex) { //nothing to do return; } long nbToBeRemoved = (long) toBufferIndex - fromBufferIndex; //fold the value if (nbToBeRemoved < 0) { nbToBeRemoved += bufLen; } final int last = this.tail; long removed = 0; int from, to; for (from = to = fromBufferIndex; from != last; from = (((from) + 1 == (bufLen)) ? 0 : (from) + 1)) { if (removed < nbToBeRemoved) { buffer[from] = (null); removed++; continue; } buffer[to] = buffer[from]; buffer[from] = (null); to = (((to) + 1 == (bufLen)) ? 0 : (to) + 1); } //end for this.tail = to; } /** * {@inheritDoc} * The position is relative to the head, * i.e w.r.t the {@link ObjectIndexedContainer}, index 0 is the head of the queue, size() - 1 is the last element position. */ @Override public void removeRange(final int fromIndex, final int toIndex) { checkRangeBounds(fromIndex, toIndex); if (fromIndex == toIndex) { return; //nothing to do } final int bufferPositionStart = indexToBufferPosition(fromIndex); final int bufferPositionEndInclusive = indexToBufferPosition(toIndex - 1); //must be a valid index removeBufferIndicesRange(bufferPositionStart, (((bufferPositionEndInclusive) + 1 == (this.buffer.length)) ? 0 : (bufferPositionEndInclusive) + 1)); } /** * Convert the internal {@link #buffer} index to equivalent {@link #ObjectIndexedContainer} * position. * @param bufferIndex * @return */ private int bufferIndexToPosition(final int bufferIndex) { int pos = -1; if (bufferIndex >= 0) { pos = bufferIndex - this.head; if (pos < 0) { //fold it pos += this.buffer.length; } } return pos; } /** * Convert the {@link #ObjectIndexedContainer} * index to the internal position in buffer{@link #buffer}. * @param index a valid index towards {@link #ObjectIndexedContainer}. * @return */ private int indexToBufferPosition(final int index) { //since the buffer is circular, we could have out-of-bounds access without JRE throwing an ArrayOutOfBoundsException, //so it is safer to do it this way. if (index < 0 || index >= size()) { throw new IndexOutOfBoundsException("Index " + index + " out of bounds [" + 0 + ", size=" + size() + "[."); } //Convert to long to prevent overflow long bufferPos = (long) index + this.head; if (bufferPos >= this.buffer.length) { //fold it bufferPos -= this.buffer.length; } return (int) bufferPos; } private void checkRangeBounds(final int beginIndex, final int endIndex) { if (beginIndex > endIndex) { throw new IllegalArgumentException("Index beginIndex " + beginIndex + " is > endIndex " + endIndex); } if (beginIndex < 0) { throw new IndexOutOfBoundsException("Index beginIndex < 0"); } if (endIndex > size()) { throw new IndexOutOfBoundsException("Index endIndex " + endIndex + " out of bounds [" + 0 + ", " + size() + "]."); } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy