com.carrotsearch.hppcrt.lists.ByteArrayList Maven / Gradle / Ivy
Show all versions of hppcrt Show documentation
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.ByteLinkedList.ValueIterator;
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 bytes. 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.
* It also has some dedicated methods to easily push, pop, and discard elements
* from the end of the array, emulating so a {@linkplain Stack java.util.Stack}.
* (see "Stack-emulating methods)
*
* See {@link ObjectArrayList} class for API similarities and differences against Java
* Collections.
*/
@javax.annotation.Generated(
date = "2016-01-27T20:51:54+0100",
value = "KTypeArrayList.java")
public class ByteArrayList
extends AbstractByteCollection implements ByteIndexedContainer, Cloneable
{
/**
* 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 byte []
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;
/**
* Default constructor: Create with default sizing strategy and initial capacity for storing
* {@link Containers#DEFAULT_EXPECTED_ELEMENTS} elements.
*
* @see BoundedProportionalArraySizingStrategy
*/
public ByteArrayList() {
this(Containers.DEFAULT_EXPECTED_ELEMENTS);
}
/**
* Create with default sizing strategy and the given initial capacity.
*
* @see BoundedProportionalArraySizingStrategy
*/
public ByteArrayList(final int initialCapacity) {
this(initialCapacity, new BoundedProportionalArraySizingStrategy());
}
/**
* Create with a custom buffer resizing strategy.
*/
public ByteArrayList(final int initialCapacity, final ArraySizingStrategy resizer) {
assert resizer != null;
this.resizer = resizer;
//allocate internal buffer
ensureBufferSpace(Math.max(Containers.DEFAULT_EXPECTED_ELEMENTS, initialCapacity));
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 = ByteArrayList.this.size();
obj.buffer = ((ByteArrayList.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 ByteArrayList(final ByteContainer container) {
this(container.size());
addAll(container);
}
/**
* {@inheritDoc}
*/
@Override
public void add(final byte 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 byte e1, final byte 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.
* @param elements
* @param start
* @param length
*/
public void add(final byte[] 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)
* @param elements
*/
public void add(final byte... elements) {
add(elements, 0, elements.length);
}
/**
* Adds all elements from another container.
* @param container
* @return the number of elements added from the container
*/
public int addAll(final ByteContainer container) {
return addAll((Iterable extends ByteCursor>) container);
}
/**
* Adds all elements from another iterable.
* @param iterable
* @return the number of elements added from the iterable
*/
public int addAll(final Iterable extends ByteCursor> iterable) {
int size = 0;
for (final ByteCursor cursor : iterable) {
add(cursor.value);
size++;
}
return size;
}
/**
* {@inheritDoc}
*/
@Override
public void insert(final int index, final byte 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 byte get(final int index) {
assert (index >= 0 && index < size()) : "Index " + index + " out of bounds [" + 0 + ", " + size() + "[.";
return ((this.buffer[index]));
}
/**
* {@inheritDoc}
*/
@Override
public byte set(final int index, final byte e1) {
assert (index >= 0 && index < size()) : "Index " + index + " out of bounds [" + 0 + ", " + size() + "[.";
final byte v = ((this.buffer[index]));
this.buffer[index] = e1;
return v;
}
/**
* {@inheritDoc}
*/
@Override
public byte remove(final int index) {
assert (index >= 0 && index < size()) : "Index " + index + " out of bounds [" + 0 + ", " + size() + "[.";
final byte 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) {
checkRangeBounds(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 removeFirst(final byte e1) {
final int index = indexOf(e1);
if (index >= 0) {
remove(index);
}
return index;
}
/**
* {@inheritDoc}
*/
@Override
public int removeLast(final byte e1) {
final int index = lastIndexOf(e1);
if (index >= 0) {
remove(index);
}
return index;
}
/**
* {@inheritDoc}
*/
@Override
public int removeAll(final byte e1) {
int to = 0;
final byte[] 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 byte e1) {
return indexOf(e1) >= 0;
}
/**
* {@inheritDoc}
*/
@Override
public int indexOf(final byte e1) {
final byte[] 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 byte e1) {
final byte[] 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.
*/
@SuppressWarnings("boxing")
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);
try {
final byte[] newBuffer = (new byte[(newSize)]);
if (bufferLen > 0) {
System.arraycopy(this.buffer, 0, newBuffer, 0, this.buffer.length);
}
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);
}
}
}
/**
* 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, ((byte)0));
}
} 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 = (byte[]) 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 = (byte[]) ByteArrays.EMPTY;
this.elementsCount = 0;
}
/**
* {@inheritDoc}
*/
@Override
public byte[] toArray(final byte[] target) {
System.arraycopy(this.buffer, 0, target, 0, this.elementsCount);
return target;
}
/**
* Clone this object.
*/
@Override
public ByteArrayList clone() {
//placeholder
final ByteArrayList cloned = new ByteArrayList(Containers.DEFAULT_EXPECTED_ELEMENTS, this.resizer);
//clone raw buffers
cloned.buffer = this.buffer.clone();
cloned.elementsCount = this.elementsCount;
return cloned;
}
/**
* {@inheritDoc}
*/
@Override
public int hashCode() {
int h = 1;
final int max = this.elementsCount;
final byte[] buffer = ((this.buffer));
for (int i = 0; i < max; i++) {
h = 31 * h + BitMixer.mix(buffer[i]);
}
return h;
}
/**
* {@inheritDoc}
*/
@Override
/* */
public boolean equals(final Object obj) {
if (obj != null) {
if (obj == this) {
return true;
}
//optimized for ByteArrayList
if (obj instanceof ByteArrayList) {
final ByteArrayList other = (ByteArrayList) obj;
return other.size() == this.size() && rangeEquals(other.buffer, this.buffer, size());
} else if (obj instanceof ByteLinkedList) { //Access by index is slow, iterate by iterator when the other is a linked list
final ByteLinkedList other = (ByteLinkedList) obj;
if (other.size() != this.size()) {
return false;
}
final ValueIterator it = this.iterator();
final ByteLinkedList.ValueIterator itOther = (ByteLinkedList.ValueIterator) other.iterator();
while (it.hasNext()) {
final byte myVal = it.next().value;
final byte otherVal = itOther.next().value;
if (!((myVal) == (otherVal))) {
//recycle
it.release();
itOther.release();
return false;
}
} //end while
itOther.release();
return true;
}
else if (obj instanceof ByteIndexedContainer) {
final ByteIndexedContainer other = (ByteIndexedContainer) obj;
return other.size() == this.size() && allIndexesEqual(this, (ByteIndexedContainer) other, this.size());
}
}
return false;
}
/**
* Compare a range of values in two arrays.
*/
private boolean rangeEquals(byte [] b1, byte [] b2, int length)
{
for (int i = 0; i < length; i++) {
if (!((b1[i]) == (b2[i]))) {
return false;
}
}
return true;
}
/**
* Compare index-aligned ByteIndexedContainer objects
*/
private boolean allIndexesEqual(final ByteIndexedContainer b1, final ByteIndexedContainer b2,
final int length) {
for (int i = 0; i < length; i++) {
final byte o1 = b1.get(i);
final byte 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 ByteCursor cursor;
private byte[] buffer;
private int size;
public ValueIterator() {
this.cursor = new ByteCursor();
this.cursor.index = -1;
this.size = ByteArrayList.this.size();
this.buffer = ((ByteArrayList.this.buffer));
}
@Override
protected ByteCursor fetch() {
if (this.cursor.index + 1 == this.size) {
return done();
}
this.cursor.value = this.buffer[++this.cursor.index];
return this.cursor;
}
}
/**
* Returns an iterator over the values of this list.
* 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 list's {@link #buffer} (which also matches index as in {@link #get(int)}), 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 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.
*/
@Override
public T forEach(final T procedure, final int fromIndex, final int toIndex) {
checkRangeBounds(fromIndex, toIndex);
final byte[] buffer = ((this.buffer));
for (int i = fromIndex; i < toIndex; i++) {
procedure.apply(buffer[i]);
}
return procedure;
}
/**
* {@inheritDoc}
*/
@Override
public int removeAll(final BytePredicate predicate) {
final int elementsCount = this.elementsCount;
final byte[] 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
.
*/
@Override
public T forEach(final T predicate, final int fromIndex, final int toIndex) {
checkRangeBounds(fromIndex, toIndex);
final byte[] 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/* */
ByteArrayList newInstance() {
return new ByteArrayList();
}
/**
* Returns a new object of this class with no need to declare generic type (shortcut
* instead of using a constructor).
*/
public static/* */
ByteArrayList newInstance(final int initialCapacity) {
return new ByteArrayList(initialCapacity);
}
/**
* Create a list from a variable number of arguments or an array of
* byte
.
*/
public static/* */
ByteArrayList from(final byte... elements) {
final ByteArrayList list = new ByteArrayList(elements.length);
list.add(elements);
return list;
}
/**
* Create a list from elements of another container.
*/
public static/* */
ByteArrayList from(final ByteContainer container) {
return new ByteArrayList(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) {
ByteSort.quicksort(this.buffer, beginIndex, endIndex);
}
/**
* In-place sort the whole list by natural ordering (smaller first)
*/
public void sort() {
sort(0, this.elementsCount);
}
////////////////////////////
/**
* In-place sort the list from [beginIndex, endIndex[
* using a ByteComparator
* @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,
ByteComparator
comp) {
ByteSort.quicksort(((this.buffer)), beginIndex, endIndex, comp);
}
/**
* In-place sort the whole list
* using a ByteComparator
*/
public void sort(
ByteComparator
comp) {
sort(0, this.elementsCount, comp);
}
///////////////////////////////////////////////////////////////////////
// Stack-like methods
///////////////////////////////////////////////////////////////////////
/**
* Stack emulating method: Adds one byte at the end of the array,
* equivalent of {@link #add(byte)}
* @param e1
*/
public void pushLast(final byte e1) {
add(e1);
}
/**
* Stack emulating method: Adds two bytes at the end of the array,
* synonym of {@link #add(byte, byte)}
* @param e1
* @param e2
*/
public void pushLast(final byte e1, final byte e2) {
add(e1, e2);
}
/**
* Stack emulating method: Adds three bytes at the end of the array
* @param e1
* @param e2
* @param e3
*/
public void pushLast(final byte e1, final byte e2, final byte e3) {
ensureBufferSpace(3);
this.buffer[this.elementsCount++] = e1;
this.buffer[this.elementsCount++] = e2;
this.buffer[this.elementsCount++] = e3;
}
/**
* Stack emulating method: Adds four bytes at the end of the array
* @param e1
* @param e2
* @param e3
* @param e4
*/
public void pushLast(final byte e1, final byte e2, final byte e3, final byte e4) {
ensureBufferSpace(4);
this.buffer[this.elementsCount++] = e1;
this.buffer[this.elementsCount++] = e2;
this.buffer[this.elementsCount++] = e3;
this.buffer[this.elementsCount++] = e4;
}
/**
* Stack emulating method: Add a range of array elements at the end of array,
* synonym of {@link #add(byte[], int, int)}
*/
public void pushLast(final byte[] elements, final int start, final int len) {
add(elements, start, len);
}
/**
* Stack emulating method: Vararg-signature method for pushing elements at the end of the array.
*
* This method is handy, but costly if used in tight loops (anonymous array
* passing)
*
*/
public final void pushLast(final byte... elements) {
add(elements, 0, elements.length);
}
/**
* Stack emulating method: Pushes all elements from another container at the end of the array,
* synonym of {@link #addAll(ByteContainer)}
*/
public int pushAllLast(final ByteContainer container) {
return addAll(container);
}
/**
* Stack emulating method: Pushes all elements from another iterable to the end of the array,
* synonym of {@link #addAll(Iterable)}
* @param iterable
*/
public int pushAllLast(final Iterable extends ByteCursor> iterable) {
return addAll(iterable);
}
/**
* Stack emulating method: Discard an arbitrary number of elements from the end of the array.
* @param count
*/
public void discardLast(final int count) {
assert this.elementsCount >= count;
this.elementsCount -= count;
/* */
}
/**
* Stack emulating method: Discard the last element of the array.
*/
public void discardLast() {
assert this.elementsCount > 0;
this.elementsCount--;
/* */
}
/**
* Stack emulating method: Discard the last element of the array, and return it.
*/
public byte popLast() {
assert this.elementsCount > 0;
final byte v = ((this.buffer[--this.elementsCount]));
/* */
return v;
}
/**
* Stack emulating method: Peek at the last element on the array.
*/
public byte peekLast() {
assert this.elementsCount > 0;
return ((this.buffer[this.elementsCount - 1]));
}
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 > this.elementsCount) {
throw new IndexOutOfBoundsException("Index endIndex " + endIndex + " out of bounds [" + 0 + ", " + this.elementsCount + "].");
}
}
}