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

com.carrotsearch.hppc.CharArrayDeque Maven / Gradle / Ivy

package com.carrotsearch.hppc;

import java.util.*;

import com.carrotsearch.hppc.cursors.CharCursor;
import com.carrotsearch.hppc.predicates.CharPredicate;
import com.carrotsearch.hppc.procedures.CharProcedure;

import static com.carrotsearch.hppc.Internals.*;

/**
 * An array-backed deque (doubly linked queue) of chars. 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.
 *
 * 

See {@link ObjectArrayDeque} class for API similarities and differences against Java * Collections. */ @javax.annotation.Generated(date = "2013-07-08T23:51:32+0200", value = "HPPC generated from: CharArrayDeque.java") public class CharArrayDeque extends AbstractCharCollection implements CharDeque, Cloneable { /** * Default capacity if no other capacity is given in the constructor. */ public final static int DEFAULT_CAPACITY = 5; /** * Internal array for storing elements. * * */ public char [] 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. */ public int tail; /** * Buffer resizing strategy. */ protected final ArraySizingStrategy resizer; /** * Create with default sizing strategy and initial capacity for storing * {@value #DEFAULT_CAPACITY} elements. * * @see BoundedProportionalArraySizingStrategy */ public CharArrayDeque() { this(DEFAULT_CAPACITY); } /** * Create with default sizing strategy and the given initial capacity. * * @see BoundedProportionalArraySizingStrategy */ public CharArrayDeque(int initialCapacity) { this(initialCapacity, new BoundedProportionalArraySizingStrategy()); } /** * Create with a custom buffer resizing strategy. */ public CharArrayDeque(int initialCapacity, ArraySizingStrategy resizer) { assert initialCapacity >= 0 : "initialCapacity must be >= 0: " + initialCapacity; assert resizer != null; this.resizer = resizer; initialCapacity = resizer.round(initialCapacity); buffer = new char [initialCapacity]; } /** * Creates a new deque from elements of another container, appending them * at the end of this deque. */ public CharArrayDeque(CharContainer container) { this(container.size()); addLast(container); } /** * {@inheritDoc} */ @Override public void addFirst(char e1) { int h = oneLeft(head, buffer.length); if (h == tail) { ensureBufferSpace(1); h = oneLeft(head, buffer.length); } buffer[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(char... 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(CharContainer container) { int size = container.size(); ensureBufferSpace(size); for (CharCursor cursor : container) { addFirst(cursor.value); } return size; } /** * 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(Iterable iterable) { int size = 0; for (CharCursor cursor : iterable) { addFirst(cursor.value); size++; } return size; } /** * {@inheritDoc} */ @Override public void addLast(char e1) { int t = oneRight(tail, buffer.length); if (head == t) { ensureBufferSpace(1); t = oneRight(tail, buffer.length); } buffer[tail] = e1; 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(char... elements) { ensureBufferSpace(1); // 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(CharContainer container) { int size = container.size(); ensureBufferSpace(size); for (CharCursor cursor : container) { addLast(cursor.value); } return size; } /** * 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(Iterable iterable) { int size = 0; for (CharCursor cursor : iterable) { addLast(cursor.value); size++; } return size; } /** * {@inheritDoc} */ @Override public char removeFirst() { assert size() > 0 : "The deque is empty."; final char result = buffer[head]; buffer[head] = ((char) 0); head = oneRight(head, buffer.length); return result; } /** * {@inheritDoc} */ @Override public char removeLast() { assert size() > 0 : "The deque is empty."; tail = oneLeft(tail, buffer.length); final char result = buffer[tail]; buffer[tail] = ((char) 0); return result; } /** * {@inheritDoc} */ @Override public char getFirst() { assert size() > 0 : "The deque is empty."; return buffer[head]; } /** * {@inheritDoc} */ @Override public char getLast() { assert size() > 0 : "The deque is empty."; return buffer[oneLeft(tail, buffer.length)]; } /** * {@inheritDoc} */ @Override public int removeFirstOccurrence(char e1) { final int index = bufferIndexOf(e1); if (index >= 0) removeAtBufferIndex(index); return index; } /** * Return the index of the first (counting from head) element equal to * e1. The index points to the {@link #buffer} array. * * @param e1 The element to look for. * @return Returns the index of the first element equal to e1 * or -1 if not found. */ public int bufferIndexOf(char e1) { final int last = tail; final int bufLen = buffer.length; for (int i = head; i != last; i = oneRight(i, bufLen)) { if (((e1) == (buffer[i]))) return i; } return -1; } /** * {@inheritDoc} */ @Override public int removeLastOccurrence(char e1) { final int index = lastBufferIndexOf(e1); if (index >= 0) removeAtBufferIndex(index); return index; } /** * Return the index of the last (counting from tail) element equal to * e1. The index points to the {@link #buffer} array. * * @param e1 The element to look for. * @return Returns the index of the first element equal to e1 * or -1 if not found. */ public int lastBufferIndexOf(char e1) { final int bufLen = buffer.length; final int last = oneLeft(head, bufLen); for (int i = oneLeft(tail, bufLen); i != last; i = oneLeft(i, bufLen)) { if (((e1) == (buffer[i]))) return i; } return -1; } /** * {@inheritDoc} */ @Override public int removeAllOccurrences(char e1) { int removed = 0; final int last = tail; final int bufLen = buffer.length; int from, to; for (from = to = head; from != last; from = oneRight(from, bufLen)) { if (((e1) == (buffer[from]))) { buffer[from] = ((char) 0); removed++; continue; } if (to != from) { buffer[to] = buffer[from]; buffer[from] = ((char) 0); } to = oneRight(to, bufLen); } tail = to; return removed; } /** * Removes the element at index in the internal * {#link {@link #buffer}} array, returning its value. * * @param index Index of the element to remove. The index must be located between * {@link #head} and {@link #tail} in modulo {@link #buffer} arithmetic. */ public void removeAtBufferIndex(int index) { assert (head <= tail ? index >= head && index < tail : index >= head || index < tail) : "Index out of range (head=" + head + ", tail=" + tail + ", index=" + index + ")."; // Cache fields in locals (hopefully moved to registers). final char [] b = this.buffer; final int bufLen = b.length; final int lastIndex = bufLen - 1; final int head = this.head; final int tail = this.tail; final int leftChunk = Math.abs(index - head) % bufLen; final int rightChunk = Math.abs(tail - index) % bufLen; if (leftChunk < rightChunk) { if (index >= head) { System.arraycopy(b, head, b, head + 1, leftChunk); } else { System.arraycopy(b, 0, b, 1, index); b[0] = b[lastIndex]; System.arraycopy(b, head, b, head + 1, lastIndex - head); } b[head] = ((char) 0); this.head = oneRight(head, bufLen); } else { if (index < tail) { System.arraycopy(b, index + 1, b, index, rightChunk); } else { System.arraycopy(b, index + 1, b, index, lastIndex - index); b[lastIndex] = b[0]; System.arraycopy(b, 1, b, 0, tail); } b[tail] = ((char) 0); this.tail = oneLeft(tail, bufLen); } } /** * {@inheritDoc} */ @Override public boolean isEmpty() { return size() == 0; } /** * {@inheritDoc} */ @Override public int size() { if (head <= tail) return tail - head; else return (tail - head + buffer.length); } /** * {@inheritDoc} * *

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

* * @see #release() */ @Override public void clear() { if (head < tail) { Arrays.fill(buffer, head, tail, ((char) 0)); } else { Arrays.fill(buffer, 0, tail, ((char) 0)); Arrays.fill(buffer, head, buffer.length, ((char) 0)); } this.head = tail = 0; } /** * Release internal buffers of this deque and reallocate the smallest buffer possible. */ public void release() { this.head = tail = 0; buffer = new char [resizer.round(DEFAULT_CAPACITY)]; } /** * Ensures the internal buffer has enough free slots to store * expectedAdditions. Increases internal buffer size if needed. */ protected void ensureBufferSpace(int expectedAdditions) { final int bufferLen = (buffer == null ? 0 : buffer.length); final int elementsCount = size(); // +1 because there is always one empty slot in a deque. if (elementsCount >= bufferLen - expectedAdditions - 1) { final int newSize = resizer.grow(bufferLen, elementsCount, expectedAdditions + 1); assert newSize >= (elementsCount + expectedAdditions + 1) : "Resizer failed to" + " return sensible new size: " + newSize + " <= " + (elementsCount + expectedAdditions); final char [] newBuffer = new char [newSize]; if (bufferLen > 0) { toArray(newBuffer); tail = elementsCount; head = 0; } this.buffer = newBuffer; } } /** * {@inheritDoc} */ @Override public char [] toArray() { final int size = size(); return toArray(new char [size]); } /** * 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. */ public char [] toArray(char [] target) { assert target.length >= size() : "Target array must be >= " + size(); if (head < tail) { // The contents is not wrapped around. Just copy. System.arraycopy(buffer, head, target, 0, size()); } else if (head > tail) { // The contents is split. Merge elements from the following indexes: // [head...buffer.length - 1][0, tail - 1] final int rightCount = buffer.length - head; System.arraycopy(buffer, head, target, 0, rightCount); System.arraycopy(buffer, 0, target, rightCount, tail); } return target; } /** * Clone this object. The returned clone will reuse the same hash function * and array resizing strategy. */ @Override public CharArrayDeque clone() { try { /* */ CharArrayDeque cloned = (CharArrayDeque) super.clone(); cloned.buffer = buffer.clone(); return cloned; } catch (CloneNotSupportedException e) { throw new RuntimeException(e); } } /** * Move one index to the left, wrapping around buffer. */ protected static int oneLeft(int index, int modulus) { if (index >= 1) return index - 1; return modulus - 1; } /** * Move one index to the right, wrapping around buffer. */ protected static int oneRight(int index, int modulus) { if (index + 1 == modulus) return 0; return index + 1; } /** * An iterator implementation for {@link ObjectArrayDeque#iterator}. */ private final class ValueIterator extends AbstractIterator { private final CharCursor cursor; private int remaining; public ValueIterator() { cursor = new CharCursor(); cursor.index = oneLeft(head, buffer.length); this.remaining = size(); } @Override protected CharCursor fetch() { if (remaining == 0) return done(); remaining--; cursor.value = buffer[cursor.index = oneRight(cursor.index, buffer.length)]; return cursor; } } /** * An iterator implementation for {@link ObjectArrayDeque#descendingIterator()}. */ private final class DescendingValueIterator extends AbstractIterator { private final CharCursor cursor; private int remaining; public DescendingValueIterator() { cursor = new CharCursor(); cursor.index = tail; this.remaining = size(); } @Override protected CharCursor fetch() { if (remaining == 0) return done(); remaining--; cursor.value = buffer[cursor.index = oneLeft(cursor.index, buffer.length)]; return cursor; } } /** * Returns a cursor 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 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);
     * }
     * 
*/ public Iterator iterator() { return new ValueIterator(); } /** * Returns a cursor 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 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);
     * }
     * 
*/ public Iterator descendingIterator() { return new DescendingValueIterator(); } /** * {@inheritDoc} */ @Override public T forEach(T procedure) { forEach(procedure, head, tail); return procedure; } /** * Applies procedure to a slice of the deque, * fromIndex, inclusive, to toIndex, * exclusive. */ private void forEach(CharProcedure procedure, int fromIndex, final int toIndex) { final char [] buffer = this.buffer; for (int i = fromIndex; i != toIndex; i = oneRight(i, buffer.length)) { procedure.apply(buffer[i]); } } /** * {@inheritDoc} */ @Override public T forEach(T predicate) { int fromIndex = head; int toIndex = tail; final char [] buffer = this.buffer; for (int i = fromIndex; i != toIndex; i = oneRight(i, buffer.length)) { if (!predicate.apply(buffer[i])) break; } return predicate; } /** * Applies procedure to all elements of this deque, tail to head. */ @Override public T descendingForEach(T procedure) { descendingForEach(procedure, head, tail); return procedure; } /** * Applies procedure to a slice of the deque, * toIndex, exclusive, down to fromIndex, inclusive. */ private void descendingForEach(CharProcedure procedure, int fromIndex, final int toIndex) { if (fromIndex == toIndex) return; final char [] buffer = this.buffer; int i = toIndex; do { i = oneLeft(i, buffer.length); procedure.apply(buffer[i]); } while (i != fromIndex); } /** * {@inheritDoc} */ @Override public T descendingForEach(T predicate) { descendingForEach(predicate, head, tail); return predicate; } /** * Applies predicate to a slice of the deque, * toIndex, exclusive, down to fromIndex, inclusive * or until the predicate returns false. */ private void descendingForEach(CharPredicate predicate, int fromIndex, final int toIndex) { if (fromIndex == toIndex) return; final char [] buffer = this.buffer; int i = toIndex; do { i = oneLeft(i, buffer.length); if (!predicate.apply(buffer[i])) break; } while (i != fromIndex); } /** * {@inheritDoc} */ @Override public int removeAll(CharPredicate predicate) { int removed = 0; final int last = tail; final int bufLen = buffer.length; int from, to; from = to = head; try { for (from = to = head; from != last; from = oneRight(from, bufLen)) { if (predicate.apply(buffer[from])) { buffer[from] = ((char) 0); removed++; continue; } if (to != from) { buffer[to] = buffer[from]; buffer[from] = ((char) 0); } to = oneRight(to, bufLen); } } finally { // Keep the deque in consistent state even if the predicate throws an exception. for (; from != last; from = oneRight(from, bufLen)) { if (to != from) { buffer[to] = buffer[from]; buffer[from] = ((char) 0); } to = oneRight(to, bufLen); } tail = to; } return removed; } /** * {@inheritDoc} */ @Override public boolean contains(char e) { int fromIndex = head; int toIndex = tail; final char [] buffer = this.buffer; for (int i = fromIndex; i != toIndex; i = oneRight(i, buffer.length)) { if (((e) == (buffer[i]))) return true; } return false; } /** * {@inheritDoc} */ @Override public int hashCode() { int h = 1; int fromIndex = head; int toIndex = tail; final char [] buffer = this.buffer; for (int i = fromIndex; i != toIndex; i = oneRight(i, buffer.length)) { h = 31 * h + rehash(this.buffer[i]); } return h; } /** * {@inheritDoc} */ @Override /* */ public boolean equals(Object obj) { if (obj != null) { if (obj instanceof CharDeque) { CharDeque other = (CharDeque) obj; if (other.size() == this.size()) { int fromIndex = head; final char [] buffer = this.buffer; int i = fromIndex; for (CharCursor c : other) { if (!((c.value) == (buffer[i]))) return false; i = oneRight(i, buffer.length); } return true; } } } return false; } /** * Returns a new object of this class with no need to declare generic type (shortcut * instead of using a constructor). */ public static /* */ CharArrayDeque newInstance() { return new CharArrayDeque(); } /** * Returns a new object of this class with no need to declare generic type (shortcut * instead of using a constructor). */ public static /* */ CharArrayDeque newInstanceWithCapacity(int initialCapacity) { return new CharArrayDeque(initialCapacity); } /** * Create a new deque by pushing a variable number of arguments to the end of it. */ public static /* */ CharArrayDeque from(char... elements) { final CharArrayDeque coll = new CharArrayDeque(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 /* */ CharArrayDeque from(CharArrayDeque container) { return new CharArrayDeque(container); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy