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

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

Go to download

High Performance Primitive Collections Realtime (fork of HPPC of Carrotsearch) Fundamental data structures (maps, sets, lists, stacks, queues, heaps, sorts) generated for combinations of object and primitive types to conserve JVM memory and speed up execution. The Realtime fork intend of extending collections while tweaking and optimizations to remove any dynamic allocations at runtime, and low variance execution times.

There is a newer version: 0.7.5
Show newest version
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); } }