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

com.carrotsearch.hppcrt.lists.CharArrayList 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.*;
import com.carrotsearch.hppcrt.strategies.*;

  
/**
 * An array-backed list 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 ObjectArrayList} class for API similarities and differences against Java * Collections. */ @javax.annotation.Generated(date = "2015-02-27T19:21:04+0100", value = "HPPC-RT generated from: CharArrayList.java") public class CharArrayList extends AbstractCharCollection implements CharIndexedContainer, Cloneable { /** * Default capacity if no other capacity is given in the constructor. */ public final static int DEFAULT_CAPACITY = 5; /** * Internal static instance of an empty buffer. */ private final static Object EMPTY = new char [0]; /** * Internal array for storing the list. The array may be larger than the current size * ({@link #size()}). * *

* Direct list iteration: iterate buffer[i] for i in [0; size()[ *

*/ public char[] buffer; /** * Current number of elements stored in {@link #buffer}. */ protected int elementsCount; /** * Buffer resizing strategy. */ protected final ArraySizingStrategy resizer; /** * internal pool of ValueIterator (must be created in constructor) */ protected final IteratorPool valueIteratorPool; /** * Create with default sizing strategy and initial capacity for storing * {@value #DEFAULT_CAPACITY} elements. * * @see BoundedProportionalArraySizingStrategy */ public CharArrayList() { this(CharArrayList.DEFAULT_CAPACITY); } /** * Create with default sizing strategy and the given initial capacity. * * @see BoundedProportionalArraySizingStrategy */ public CharArrayList(final int initialCapacity) { this(initialCapacity, new BoundedProportionalArraySizingStrategy()); } /** * Create with a custom buffer resizing strategy. */ public CharArrayList(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 = (new char[internalSize]); this.valueIteratorPool = new IteratorPool( new ObjectFactory() { @Override public ValueIterator create() { return new ValueIterator(); } @Override public void initialize(final ValueIterator obj) { obj.cursor.index = -1; obj.size = CharArrayList.this.size(); obj.buffer = CharArrayList.this.buffer; } @Override public void reset(final ValueIterator obj) { // for GC sake obj.buffer = null; } }); } /** * Creates a new list from elements of another container. */ public CharArrayList(final CharContainer container) { this(container.size()); addAll(container); } /** * {@inheritDoc} */ @Override public void add(final char e1) { ensureBufferSpace(1); this.buffer[this.elementsCount++] = 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 char e1, final char e2) { ensureBufferSpace(2); this.buffer[this.elementsCount++] = e1; this.buffer[this.elementsCount++] = e2; } /** * Add all elements from a range of given array to the list. */ public void add(final char[] elements, final int start, final int length) { assert length >= 0 : "Length must be >= 0"; ensureBufferSpace(length); System.arraycopy(elements, start, this.buffer, this.elementsCount, length); this.elementsCount += 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 char... elements) { add(elements, 0, elements.length); } /** * Adds all elements from another container. */ public int addAll(final CharContainer container) { return addAll((Iterable) container); } /** * Adds all elements from another iterable. */ public int addAll(final Iterable iterable) { int size = 0; for (final CharCursor cursor : iterable) { add(cursor.value); size++; } return size; } /** * {@inheritDoc} */ @Override public void insert(final int index, final char e1) { assert (index >= 0 && index <= size()) : "Index " + index + " out of bounds [" + 0 + ", " + size() + "]."; ensureBufferSpace(1); System.arraycopy(this.buffer, index, this.buffer, index + 1, this.elementsCount - index); this.buffer[index] = e1; this.elementsCount++; } /** * {@inheritDoc} */ @Override public char get(final int index) { assert (index >= 0 && index < size()) : "Index " + index + " out of bounds [" + 0 + ", " + size() + ")."; return this.buffer[index]; } /** * {@inheritDoc} */ @Override public char set(final int index, final char e1) { assert (index >= 0 && index < size()) : "Index " + index + " out of bounds [" + 0 + ", " + size() + ")."; final char v = this.buffer[index]; this.buffer[index] = e1; return v; } /** * {@inheritDoc} */ @Override public char remove(final int index) { assert (index >= 0 && index < size()) : "Index " + index + " out of bounds [" + 0 + ", " + size() + ")."; final char v = this.buffer[index]; if (index + 1 < this.elementsCount) { System.arraycopy(this.buffer, index + 1, this.buffer, index, this.elementsCount - index - 1); } this.elementsCount--; return v; } /** * {@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; System.arraycopy(this.buffer, toIndex, this.buffer, fromIndex, this.elementsCount - toIndex); final int count = toIndex - fromIndex; this.elementsCount -= count; } /** * {@inheritDoc} */ @Override public int removeFirstOccurrence(final char e1) { final int index = indexOf(e1); if (index >= 0) { remove(index); } return index; } /** * {@inheritDoc} */ @Override public int removeLastOccurrence(final char e1) { final int index = lastIndexOf(e1); if (index >= 0) { remove(index); } return index; } /** * {@inheritDoc} */ @Override public int removeAllOccurrences(final char e1) { int to = 0; final char[] buffer = this.buffer; for (int from = 0; from < this.elementsCount; from++) { if ((e1 == buffer[from])) { continue; } if (to != from) { buffer[to] = buffer[from]; } to++; } final int deleted = this.elementsCount - to; this.elementsCount = to; return deleted; } /** * {@inheritDoc} */ @Override public boolean contains(final char e1) { return indexOf(e1) >= 0; } /** * {@inheritDoc} */ @Override public int indexOf(final char e1) { final char[] buffer = this.buffer; for (int i = 0; i < this.elementsCount; i++) { if ((e1 == buffer[i])) { return i; } } return -1; } /** * {@inheritDoc} */ @Override public int lastIndexOf(final char e1) { final char[] buffer = this.buffer; for (int i = this.elementsCount - 1; i >= 0; i--) { if ((e1 == buffer[i])) { return i; } } 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. */ protected void 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); final char[] newBuffer = (new char[newSize]); if (bufferLen > 0) { System.arraycopy(this.buffer, 0, newBuffer, 0, this.buffer.length); } this.buffer = newBuffer; } } /** * Truncate or expand the list to the new size. If the list is truncated, the buffer * will not be reallocated (use {@link #trimToSize()} if you need a truncated buffer). * If the list is expanded, the elements beyond the current size are initialized with JVM-defaults * (zero or null values). */ public void resize(final int newSize) { if (newSize <= this.buffer.length) { if (newSize < this.elementsCount) { //there is no point in resetting to "null" elements //that becomes non-observable anyway. Still, //resetting is needed for GC in case of Objects because they may become "free" //if not referenced anywhere else. } else { //in all cases, the contract of resize if that new elements //are set to default values. Arrays.fill(this.buffer, this.elementsCount, newSize, ('\u0000')); } } else { ensureCapacity(newSize); } this.elementsCount = newSize; } /** * {@inheritDoc} */ @Override public int size() { return this.elementsCount; } /** * {@inheritDoc} */ @Override public int capacity() { return this.buffer.length; } /** * Trim the internal buffer to the current size. */ /* */ public void trimToSize() { if (size() != this.buffer.length) { this.buffer = (char[]) toArray(); } } /** * Sets the number of stored elements to zero. */ @Override public void clear() { this.elementsCount = 0; } /** * Sets the number of stored elements to zero and releases the internal storage array. */ /* */ public void release() { this.buffer = (char[]) CharArrayList.EMPTY; this.elementsCount = 0; } /** * {@inheritDoc} */ @Override public char[] toArray(final char[] target) { System.arraycopy(this.buffer, 0, target, 0, this.elementsCount); 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 CharArrayList clone() { /* */ final CharArrayList cloned = new CharArrayList(this.size(), this.resizer); cloned.defaultValue = this.defaultValue; //add all in order, by construction. cloned.addAll(this); return cloned; } /** * {@inheritDoc} */ @Override public int hashCode() { int h = 1; final int max = this.elementsCount; final char[] buffer = this.buffer; for (int i = 0; i < max; i++) { h = 31 * h + Internals.rehash(buffer[i]); } return h; } /** * {@inheritDoc} */ @Override /* */ public boolean equals(final Object obj) { if (obj != null) { if (obj == this) { return true; } if (obj instanceof CharArrayList) { final CharArrayList other = (CharArrayList) obj; return other.size() == this.size() && rangeEquals(other.buffer, this.buffer, size()); } else if (obj instanceof CharIndexedContainer) { final CharIndexedContainer other = (CharIndexedContainer) obj; return other.size() == this.size() && allIndexesEqual(this, (CharIndexedContainer) other, this.size()); } } return false; } /** * Compare a range of values in two arrays. */ private boolean rangeEquals(char [] b1, char [] b2, int length) { for (int i = 0; i < length; i++) { if (!(b1[i] == b2[i])) { return false; } } return true; } /** * Compare index-aligned CharIndexedContainer objects */ final protected boolean allIndexesEqual( final CharIndexedContainer b1, final CharIndexedContainer b2, final int length) { for (int i = 0; i < length; i++) { final char o1 = b1.get(i); final char o2 = b2.get(i); if (!(o1 == o2)) { return false; } } return true; } /** * An iterator implementation for {@link ObjectArrayList#iterator}. */ public final class ValueIterator extends AbstractIterator { public final CharCursor cursor; private char[] buffer; private int size; public ValueIterator() { this.cursor = new CharCursor(); this.cursor.index = -1; this.size = CharArrayList.this.size(); this.buffer = CharArrayList.this.buffer; } @Override protected CharCursor fetch() { if (this.cursor.index + 1 == this.size) { return done(); } this.cursor.value = this.buffer[++this.cursor.index]; return this.cursor; } } /** * {@inheritDoc} * @return */ @Override public ValueIterator iterator() { //return new ValueIterator(buffer, size()); return this.valueIteratorPool.borrow(); } /** * {@inheritDoc} */ @Override public T forEach(final T procedure) { return forEach(procedure, 0, size()); } /** * Applies procedure to a slice of the list, * fromIndex, inclusive, to toIndex, * exclusive. */ public T forEach(final T procedure, 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; final char[] buffer = this.buffer; for (int i = fromIndex; i < toIndex; i++) { procedure.apply(buffer[i]); } return procedure; } /** * {@inheritDoc} */ @Override public int removeAll(final CharPredicate predicate) { final int elementsCount = this.elementsCount; final char[] buffer = this.buffer; int to = 0; int from = 0; try { for (; from < elementsCount; from++) { if (predicate.apply(buffer[from])) { continue; } if (to != from) { buffer[to] = buffer[from]; } to++; } } finally { // Keep the list in a consistent state, even if the predicate throws an exception. for (; from < elementsCount; from++) { if (to != from) { buffer[to] = buffer[from]; } to++; } this.elementsCount = to; } return elementsCount - to; } /** * {@inheritDoc} */ @Override public T forEach(final T predicate) { return forEach(predicate, 0, size()); } /** * Applies predicate to a slice of the list, * fromIndex, inclusive, to toIndex, * exclusive, or until predicate returns false. */ public T forEach(final T predicate, 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; final char[] buffer = this.buffer; for (int i = fromIndex; i < toIndex; i++) { if (!predicate.apply(buffer[i])) { break; } } return predicate; } /** * Returns a new object of this class with no need to declare generic type (shortcut * instead of using a constructor). */ public static/* */ CharArrayList newInstance() { return new CharArrayList(); } /** * Returns a new object of this class with no need to declare generic type (shortcut * instead of using a constructor). */ public static/* */ CharArrayList newInstanceWithCapacity(final int initialCapacity) { return new CharArrayList(initialCapacity); } /** * Create a list from a variable number of arguments or an array of char. * The elements are copied from the argument to the internal buffer. */ public static/* */ CharArrayList from(final char... elements) { final CharArrayList list = new CharArrayList(elements.length); list.add(elements); return list; } /** * Create a list from elements of another container. */ public static/* */ CharArrayList from(final CharContainer container) { return new CharArrayList(container); } /** * In-place sort the list 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) */ public void sort(final int beginIndex, final int endIndex) { assert endIndex <= this.elementsCount; if (endIndex - beginIndex > 1) { CharSort.quicksort(this.buffer, beginIndex, endIndex); } } /** * In-place sort the whole list by natural ordering (smaller first) *

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

*/ public void sort() { sort(0, this.elementsCount); } //////////////////////////// /** * In-place sort the list from [beginIndex, endIndex[ * using a CharComparator *

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

* @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, CharComparator comp) { assert endIndex <= this.elementsCount; if (endIndex - beginIndex > 1) { CharSort.quicksort(this.buffer, beginIndex, endIndex, comp); } } /** * In-place sort the whole list * using a CharComparator *

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

*/ public void sort( CharComparator comp) { sort(0, this.elementsCount, comp); } }