/*
* Javolution - Java(TM) Solution for Real-Time and Embedded Systems
* Copyright (C) 2005 - Javolution (http://javolution.org/)
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software is
* freely granted, provided that this notice is preserved.
*/
package javolution.util;
import java.io.IOException;
import java.util.NoSuchElementException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.IllegalStateException;
import java.lang.UnsupportedOperationException;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.RandomAccess;
import javax.realtime.MemoryArea;
import javolution.context.ObjectFactory;
import javolution.context.PersistentContext;
import javolution.lang.MathLib;
import javolution.lang.Reusable;
/**
* <p> This class represents a random access collection with real-time behavior
* (smooth capacity increase).</p>
* <img src="doc-files/list-add.png"/>
*
* <p> This class has the following advantages over the widely used
* <code>java.util.ArrayList</code>:<ul>
* <li> No large array allocation (for large collections multi-dimensional
* arrays are employed). The garbage collector is not stressed with
* large chunk of memory to allocate (likely to trigger a
* full garbage collection due to memory fragmentation).</li>
* <li> Support concurrent access/iteration/modification without synchronization
* if marked {@link FastCollection#shared shared}. </li>
* </ul></p>
*
* <p> Iterations over the {@link FastTable} values are faster when
* performed using the {@link #get} method rather than using collection
* records or iterators:[code]
* for (int i = 0, n = table.size(); i < n; i++) {
* table.get(i);
* }[/code]</p>
*
* <p> {@link FastTable} supports {@link #sort sorting} in place (quick sort)
* using the {@link FastCollection#getValueComparator() value comparator}
* for the table (no object or array allocation when sorting).</p>
*
* @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
* @version 5.4.5, August 20, 2007
*/
public class FastTable <E> extends FastCollection <E> implements
List <E> , Reusable, RandomAccess {
/**
* Holds the factory for this fast table.
*/
private static final ObjectFactory FACTORY = new ObjectFactory() {
public Object create() {
return new FastTable();
}
};
// We do a full resize (and copy) only when the capacity is less than C1.
// For large collections, multi-dimensional arrays are employed.
private static final int B0 = 4; // Initial capacity in bits.
private static final int C0 = 1 << B0; // Initial capacity (16)
private static final int B1 = 10; // Low array maximum capacity in bits.
private static final int C1 = 1 << B1; // Low array maximum capacity (1024).
private static final int M1 = C1 - 1; // Mask.
// Resizes up to 1024 maximum (16, 32, 64, 128, 256, 512, 1024).
private transient E [] _low;
// For larger capacity use multi-dimensional array.
private transient E [][] _high;
/**
* Holds the current capacity.
*/
private transient int _capacity;
/**
* Holds the current size. Volatility ensures that when elements are
* added
*/
private transient int _size;
/**
* Holds the value comparator.
*/
private transient FastComparator <? super E> _valueComparator = FastComparator.DEFAULT;
/**
* Creates a table of small initial capacity.
*/
public FastTable() {
_capacity = C0;
_low = ( E []) new Object[C0];
_high = ( E [][]) new Object[1][];
_high[0] = _low;
}
/**
* Creates a persistent table associated to the specified unique identifier
* (convenience method).
*
* @param id the unique identifier for this map.
* @throws IllegalArgumentException if the identifier is not unique.
* @see javolution.context.PersistentContext.Reference
*/
public FastTable(String id) {
this();
new PersistentContext.Reference(id, this) {
protected void notifyChange() {
FastTable.this.clear();
FastTable.this.addAll((FastList) this.get());
}
};
}
/**
* Creates a table of specified initial capacity; unless the table size
* reaches the specified capacity, operations on this table will not
* allocate memory (no lazy object creation).
*
* @param capacity the initial capacity.
*/
public FastTable(int capacity) {
this();
while (capacity > _capacity) {
increaseCapacity();
}
}
/**
* Creates a table containing the specified values, in the order they
* are returned by the collection's iterator.
*
* @param values the values to be placed into this table.
*/
public FastTable(Collection <? extends E> values) {
this(values.size());
addAll(values);
}
/**
* Returns a new, preallocated or {@link #recycle recycled} table instance
* (on the stack when executing in a {@link javolution.context.StackContext
* StackContext}).
*
* @return a new, preallocated or recycled table instance.
*/
public static <E> FastTable <E> newInstance() {
return (FastTable <E> ) FACTORY.object();
}
/**
* Recycles a table {@link #newInstance() instance} immediately
* (on the stack when executing in a {@link javolution.context.StackContext
* StackContext}).
*/
public static void recycle(FastTable instance) {
FACTORY.recycle(instance);
}
/**
* Sets the size of this table. If the specified size is greater than
* the current size then <code>null</code> elements are added; otherwise
* the last elements are removed until the desired size is reached.
*
* @param size the new size.
*/
public void setSize(int size) {
while (_size < size) { // Adds null elements.
addLast(null);
}
while (_size > size) { // Removes last elements.
removeLast();
}
}
/**
* Returns the element at the specified index.
*
* @param index index of value to return.
* @return the value at the specified position in this list.
* @throws IndexOutOfBoundsException if <code>(index < 0) ||
* (index >= size())</code>
*/
public final E get(int index) { // Short to be inlined.
if (index >= _size)
throw new IndexOutOfBoundsException();
return index < C1 ? _low[index] : _high[index >> B1][index & M1];
}
/**
* Replaces the value at the specified position in this table with the
* specified value.
*
* @param index index of value to replace.
* @param value value to be stored at the specified position.
* @return previous value.
* @throws IndexOutOfBoundsException if <code>(index < 0) ||
* (index >= size())</code>
*/
public final E set(int index, E value) {
if (index >= _size)
throw new IndexOutOfBoundsException();
final E [] low = _high[index >> B1];
final E previous = low[index & M1];
low[index & M1] = value;
return previous;
}
/**
* Appends the specified value to the end of this table.
*
* @param value the value to be appended to this table.
* @return <code>true</code> (as per the general contract of the
* <code>Collection.add</code> method).
*/
public final boolean add( E value) {
if (_size >= _capacity)
increaseCapacity();
_high[_size >> B1][_size & M1] = value;
_size++;
return true;
}
/**
* Returns the first value of this table.
*
* @return this table first value.
* @throws NoSuchElementException if this table is empty.
*/
public final E getFirst() {
if (_size == 0)
throw new NoSuchElementException();
return _low[0];
}
/**
* Returns the last value of this table.
*
* @return this table last value.
* @throws NoSuchElementException if this table is empty.
*/
public final E getLast() {
if (_size == 0)
throw new NoSuchElementException();
return get(_size - 1);
}
/**
* Appends the specified value to the end of this table <i>(fast)</i>.
*
* @param value the value to be added.
*/
public final void addLast( E value) {
add(value);
}
/**
* Removes and returns the last value of this table <i>(fast)</i>.
*
* @return this table's last value before this call.
* @throws NoSuchElementException if this table is empty.
*/
public final E removeLast() {
if (_size == 0)
throw new NoSuchElementException();
_size--; // No need for volatile, removal are not thread-safe.
final E [] low = _high[_size >> B1];
final E previous = low[_size & M1];
low[_size & M1] = null;
return previous;
}
// Overrides.
public final void clear() {
for (int i = 0; i < _size; i += C1) {
final int count = MathLib.min(_size - i, C1);
final E [] low = _high[i >> B1];
System.arraycopy(NULL_BLOCK, 0, low, 0, count);
}
_size = 0; // No need for volatile, removal are not thread-safe.
}
private static final Object[] NULL_BLOCK = (Object[]) new Object[C1];
// Implements Reusable interface.
public void reset() {
clear();
this.setValueComparator(FastComparator.DEFAULT);
}
/**
* Inserts all of the values in the specified collection into this
* table at the specified position. Shifts the value currently at that
* position (if any) and any subsequent values to the right
* (increases their indices).
*
* <p>Note: If this method is used concurrent access must be synchronized
* (the table is no more thread-safe).</p>
*
* @param index the index at which to insert first value from the specified
* collection.
* @param values the values to be inserted into this list.
* @return <code>true</code> if this list changed as a result of the call;
* <code>false</code> otherwise.
* @throws IndexOutOfBoundsException if <code>(index < 0) ||
* (index > size())</code>
*/
public final boolean addAll(int index, Collection <? extends E> values) {
if ((index < 0) || (index > _size))
throw new IndexOutOfBoundsException("index: " + index);
final int shift = values.size();
shiftRight(index, shift);
Iterator <? extends E> valuesIterator = values.iterator();
for (int i = index, n = index + shift; i < n; i++) {
_high[i >> B1][i & M1] = valuesIterator.next();
}
_size += shift; // Increases size last (thread-safe)
return shift != 0;
}
/**
* Inserts the specified value at the specified position in this table.
* Shifts the value currently at that position
* (if any) and any subsequent values to the right (adds one to their
* indices).
*
* <p>Note: If this method is used concurrent access must be synchronized
* (the table is no more thread-safe).</p>
*
* @param index the index at which the specified value is to be inserted.
* @param value the value to be inserted.
* @throws IndexOutOfBoundsException if <code>(index < 0) ||
* (index > size())</code>
*/
public final void add(int index, E value) {
if ((index < 0) || (index > _size))
throw new IndexOutOfBoundsException("index: " + index);
shiftRight(index, 1);
_high[index >> B1][index & M1] = value;
_size++;
}
/**
* Removes the value at the specified position from this table.
* Shifts any subsequent values to the left (subtracts one
* from their indices). Returns the value that was removed from the
* table.
*
* <p>Note: If this method is used concurrent access must be synchronized
* (the table is no more thread-safe).</p>
*
* @param index the index of the value to removed.
* @return the value previously at the specified position.
* @throws IndexOutOfBoundsException if <code>(index < 0) ||
* (index >= size())</code>
*/
public final E remove(int index) {
final E previous = get(index);
shiftLeft(index + 1, 1);
_size--; // No need for volatile, removal are not thread-safe.
_high[_size >> B1][_size & M1] = null; // Deallocates for GC.
return previous;
}
/**
* Removes the values between <code>[fromIndex..toIndex[<code> from
* this table.
*
* <p>Note: If this method is used concurrent access must be synchronized
* (the table is no more thread-safe).</p>
*
* @param fromIndex the beginning index, inclusive.
* @param toIndex the ending index, exclusive.
* @throws IndexOutOfBoundsException if <code>(fromIndex < 0) || (toIndex < 0)
* || (fromIndex > toIndex) || (toIndex > this.size())</code>
*/
public final void removeRange(int fromIndex, int toIndex) {
if ((fromIndex < 0) || (toIndex < 0) || (fromIndex > toIndex)
|| (toIndex > _size))
throw new IndexOutOfBoundsException("FastTable removeRange(" + fromIndex + ", " + toIndex + ") index out of bounds, size: " + _size);
final int shift = toIndex - fromIndex;
shiftLeft(toIndex, shift);
_size -= shift; // No need for volatile, removal are not thread-safe.
for (int i = _size, n = _size + shift; i < n; i++) {
_high[i >> B1][i & M1] = null; // Deallocates for GC.
}
}
/**
* Returns the index in this table of the first occurrence of the specified
* value, or -1 if this table does not contain this value.
*
* @param value the value to search for.
* @return the index in this table of the first occurrence of the specified
* value, or -1 if this table does not contain this value.
*/
public final int indexOf(Object value) {
final FastComparator comp = this.getValueComparator();
for (int i = 0; i < _size;) {
final E [] low = _high[i >> B1];
final int count = MathLib.min(low.length, _size - i);
for (int j = 0; j < count; j++) {
if (comp == FastComparator.DEFAULT ? defaultEquals(value,
low[j]) : comp.areEqual(value, low[j]))
return i + j;
}
i += count;
}
return -1;
}
/**
* Returns the index in this table of the last occurrence of the specified
* value, or -1 if this table does not contain this value.
*
* @param value the value to search for.
* @return the index in this table of the last occurrence of the specified
* value, or -1 if this table does not contain this value.
*/
public final int lastIndexOf(Object value) {
final FastComparator comp = this.getValueComparator();
for (int i = _size - 1; i >= 0;) {
final E [] low = _high[i >> B1];
final int count = (i & M1) + 1;
for (int j = count; --j >= 0;) {
if (comp == FastComparator.DEFAULT ? defaultEquals(value,
low[j]) : comp.areEqual(value, low[j]))
return i + j - count + 1;
}
i -= count;
}
return -1;
}
/**
* Returns an iterator over the elements in this list
* (allocated on the stack when executed in a
* {@link javolution.context.StackContext StackContext}).
*
* @return an iterator over this list values.
*/
public Iterator <E> iterator() {
return FastTableIterator.valueOf(this, 0, 0, _size);
}
/**
* Returns a list iterator over the elements in this list
* (allocated on the stack when executed in a
* {@link javolution.context.StackContext StackContext}).
*
* @return an iterator over this list values.
*/
public ListIterator <E> listIterator() {
return FastTableIterator.valueOf(this, 0, 0, _size);
}
/**
* Returns a list iterator from the specified position
* (allocated on the stack when executed in a
* {@link javolution.context.StackContext StackContext}).
* The list iterator being returned does not support insertion/deletion.
*
* @param index the index of first value to be returned from the
* list iterator (by a call to the <code>next</code> method).
* @return a list iterator of the values in this table
* starting at the specified position in this list.
* @throws IndexOutOfBoundsException if the index is out of range
* [code](index < 0 || index > size())[/code]
*/
public ListIterator <E> listIterator(int index) {
if ((index < 0) || (index > _size)) throw new IndexOutOfBoundsException();
return FastTableIterator.valueOf(this, index, 0, _size);
}
/**
* Returns a view of the portion of this list between the specified
* indexes (instance of {@link FastList} allocated from the "stack" when
* executing in a {@link javolution.context.StackContext StackContext}).
* If the specified indexes are equal, the returned list is empty.
* The returned list is backed by this list, so non-structural changes in
* the returned list are reflected in this list, and vice-versa.
*
* This method eliminates the need for explicit range operations (of
* the sort that commonly exist for arrays). Any operation that expects
* a list can be used as a range operation by passing a subList view
* instead of a whole list. For example, the following idiom
* removes a range of values from a list: [code]
* list.subList(from, to).clear();[/code]
* Similar idioms may be constructed for <code>indexOf</code> and
* <code>lastIndexOf</code>, and all of the algorithms in the
* <code>Collections</code> class can be applied to a subList.
*
* The semantics of the list returned by this method become undefined if
* the backing list (i.e., this list) is <i>structurally modified</i> in
* any way other than via the returned list (structural modifications are
* those that change the size of this list, or otherwise perturb it in such
* a fashion that iterations in progress may yield incorrect results).
*
* @param fromIndex low endpoint (inclusive) of the subList.
* @param toIndex high endpoint (exclusive) of the subList.
* @return a view of the specified range within this list.
*
* @throws IndexOutOfBoundsException if [code](fromIndex < 0 ||
* toIndex > size || fromIndex > toIndex)[/code]
*/
public final List <E> subList(int fromIndex, int toIndex) {
if ((fromIndex < 0) || (toIndex > _size) || (fromIndex > toIndex))
throw new IndexOutOfBoundsException("fromIndex: " + fromIndex
+ ", toIndex: " + toIndex + " for list of size: " + _size);
return SubTable.valueOf(this, fromIndex, toIndex - fromIndex);
}
/**
* Reduces the capacity of this table to the current size (minimize
* storage space).
*/
public final void trimToSize() {
while (_capacity - _size > C1) {
_capacity -= C1;
_high[_capacity >> B1] = null;
}
}
/**
* Sorts this table in place (quick sort) using this table
* {@link FastCollection#getValueComparator() value comparator}
* (smallest first).
*
* @return <code>this</code>
*/
public final FastTable <E> sort() {
if (_size > 1) {
quicksort(0, _size - 1, this.getValueComparator());
}
return this;
}
// From Wikipedia Quick Sort - http://en.wikipedia.org/wiki/Quicksort
//
private void quicksort(int first, int last, FastComparator cmp) {
int pivIndex = 0;
if (first < last) {
pivIndex = partition(first, last, cmp);
quicksort(first, (pivIndex - 1), cmp);
quicksort((pivIndex + 1), last, cmp);
}
}
private int partition(int f, int l, FastComparator cmp) {
int up, down;
E piv = get(f);
up = f;
down = l;
do {
while (cmp.compare(get(up), piv) <= 0 && up < l) {
up++;
}
while (cmp.compare(get(down), piv) > 0 && down > f) {
down--;
}
if (up < down) { // Swaps.
E temp = get(up);
set(up, get(down));
set(down, temp);
}
} while (down > up);
set(f, get(down));
set(down, piv);
return down;
}
/**
* Sets the comparator to use for value equality or comparison if the
* collection is ordered (see {@link #sort()}).
*
* @param comparator the value comparator.
* @return <code>this</code>
*/
public FastTable <E> setValueComparator(
FastComparator <? super E> comparator) {
_valueComparator = comparator;
return this;
}
// Overrides.
public FastComparator <? super E> getValueComparator() {
return _valueComparator;
}
// Implements FastCollection abstract method.
public final int size() {
return _size;
}
// Implements FastCollection abstract method.
public final Record head() {
return Index.valueOf(-1);
}
// Implements FastCollection abstract method.
public final Record tail() {
return Index.valueOf(_size);
}
// Implements FastCollection abstract method.
public final E valueOf(Record record) {
return get(((Index) record).intValue());
}
// Implements FastCollection abstract method.
public final void delete(Record record) {
remove(((Index) record).intValue());
}
// Overrides to return a list (JDK1.5+).
public List<E> unmodifiable() {
return ( List<E> ) super.unmodifiable();
}
// Overrides (optimization).
public final boolean contains(Object value) {
return indexOf(value) >= 0;
}
// Requires special handling during de-serialization process.
private void readObject(ObjectInputStream stream) throws IOException,
ClassNotFoundException {
setValueComparator((FastComparator) stream.readObject());
final int size = stream.readInt();
_capacity = C0;
while ((_capacity < _size) && (_capacity < C1)) {
_capacity <<= 1; // Increases capacity up to C1 to avoid resizes.
}
_low = ( E []) new Object[_capacity];
_high = ( E [][]) new Object[1][];
_high[0] = _low;
for (int i = 0; i < size; i++) {
addLast(( E ) stream.readObject());
}
}
// Requires special handling during serialization process.
private void writeObject(ObjectOutputStream stream) throws IOException {
stream.writeObject(getValueComparator());
final int size = _size;
stream.writeInt(size);
for (int i = 0; i < size; i++) {
stream.writeObject(get(i));
}
}
/**
* Returns the current capacity of this table.
*
* @return this table's capacity.
*/
protected final int getCapacity() {
return _capacity;
}
/**
* Increases this table capacity.
*/
private void increaseCapacity() {
MemoryArea.getMemoryArea(this).executeInArea(new Runnable() {
public void run() {
if (_capacity < C1) { // For small capacity, resize.
_capacity <<= 1;
E [] tmp = ( E []) new Object[_capacity];
System.arraycopy(_low, 0, tmp, 0, _size);
_low = tmp;
_high[0] = tmp;
} else { // Add a new low block of 1024 elements.
int j = _capacity >> B1;
if (j >= _high.length) { // Resizes _high.
E [][] tmp = ( E [][]) new Object[_high.length * 2][];
System.arraycopy(_high, 0, tmp, 0, _high.length);
_high = tmp;
}
_high[j] = ( E []) new Object[C1];
_capacity += C1;
}
}
});
}
/**
* This inner class implements a sub-table.
*/
private static final class SubTable extends FastCollection implements List,
RandomAccess {
private static final ObjectFactory FACTORY = new ObjectFactory() {
protected Object create() {
return new SubTable();
}
protected void cleanup(Object obj) {
SubTable st = (SubTable) obj;
st._table = null;
}
};
private FastTable _table;
private int _offset;
private int _size;
public static SubTable valueOf(FastTable table, int offset, int size) {
SubTable subTable = (SubTable) FACTORY.object();
subTable._table = table;
subTable._offset = offset;
subTable._size = size;
return subTable;
}
public int size() {
return _size;
}
public Record head() {
return Index.valueOf(-1);
}
public Record tail() {
return Index.valueOf(_size);
}
public Object valueOf(Record record) {
return _table.get(((Index) record).intValue() + _offset);
}
public void delete(Record record) {
throw new UnsupportedOperationException(
"Deletion not supported, thread-safe collections.");
}
public boolean addAll(int index, Collection values) {
throw new UnsupportedOperationException(
"Insertion not supported, thread-safe collections.");
}
public Object get(int index) {
if ((index < 0) || (index >= _size))
throw new IndexOutOfBoundsException("index: " + index);
return _table.get(index + _offset);
}
public Object set(int index, Object value) {
if ((index < 0) || (index >= _size))
throw new IndexOutOfBoundsException("index: " + index);
return _table.set(index + _offset, value);
}
public void add(int index, Object element) {
throw new UnsupportedOperationException(
"Insertion not supported, thread-safe collections.");
}
public Object remove(int index) {
throw new UnsupportedOperationException(
"Deletion not supported, thread-safe collections.");
}
public int indexOf(Object value) {
final FastComparator comp = _table.getValueComparator();
for (int i = -1; ++i < _size;) {
if (comp.areEqual(value, _table.get(i + _offset)))
return i;
}
return -1;
}
public int lastIndexOf(Object value) {
final FastComparator comp = _table.getValueComparator();
for (int i = _size; --i >= 0;) {
if (comp.areEqual(value, _table.get(i + _offset)))
return i;
}
return -1;
}
public ListIterator listIterator() {
return listIterator(0);
}
public ListIterator listIterator(int index) {
if ((index >= 0) && (index <= _size)) {
return FastTableIterator.valueOf(_table, index + _offset,
_offset, _offset + _size);
} else {
throw new IndexOutOfBoundsException("index: " + index
+ " for table of size: " + _size);
}
}
public List subList(int fromIndex, int toIndex) {
if ((fromIndex < 0) || (toIndex > _size) || (fromIndex > toIndex))
throw new IndexOutOfBoundsException("fromIndex: " + fromIndex
+ ", toIndex: " + toIndex + " for list of size: "
+ _size);
return SubTable.valueOf(_table, _offset + fromIndex, toIndex
- fromIndex);
}
}
/**
* This inner class implements a fast table iterator.
*/
private static final class FastTableIterator implements ListIterator {
private static final ObjectFactory FACTORY = new ObjectFactory() {
protected Object create() {
return new FastTableIterator();
}
protected void cleanup(Object obj) {
FastTableIterator i = (FastTableIterator) obj;
i._table = null;
i._low = null;
i._high = null;
}
};
private FastTable _table;
private int _currentIndex;
private int _start; // Inclusive.
private int _end; // Exclusive.
private int _nextIndex;
private Object[] _low;
private Object[][] _high;
public static FastTableIterator valueOf(FastTable table, int nextIndex,
int start, int end) {
FastTableIterator iterator = (FastTableIterator) FACTORY.object();
iterator._table = table;
iterator._start = start;
iterator._end = end;
iterator._nextIndex = nextIndex;
iterator._low = table._low;
iterator._high = table._high;
iterator._currentIndex = -1;
return iterator;
}
public boolean hasNext() {
return (_nextIndex != _end);
}
public Object next() {
if (_nextIndex == _end)
throw new NoSuchElementException();
final int i = _currentIndex = _nextIndex++;
return i < C1 ? _low[i] : _high[i >> B1][i & M1];
}
public int nextIndex() {
return _nextIndex;
}
public boolean hasPrevious() {
return _nextIndex != _start;
}
public Object previous() {
if (_nextIndex == _start)
throw new NoSuchElementException();
final int i = _currentIndex = --_nextIndex;
return i < C1 ? _low[i] : _high[i >> B1][i & M1];
}
public int previousIndex() {
return _nextIndex - 1;
}
public void add(Object o) {
_table.add(_nextIndex++, o);
_end++;
_currentIndex = -1;
}
public void set(Object o) {
if (_currentIndex >= 0) {
_table.set(_currentIndex, o);
} else {
throw new IllegalStateException();
}
}
public void remove() {
if (_currentIndex >= 0) {
_table.remove(_currentIndex);
_end--;
if (_currentIndex < _nextIndex) {
_nextIndex--;
}
_currentIndex = -1;
} else {
throw new IllegalStateException();
}
}
}
// Shifts element from the specified index to the right (higher indexes).
private void shiftRight(int index, int shift) {
while (_size + shift >= _capacity) {
increaseCapacity();
}
for (int i = _size; --i >= index;) {
final int dest = i + shift;
_high[dest >> B1][dest & M1] = _high[i >> B1][i & M1];
}
}
// Shifts element from the specified index to the left (lower indexes).
private void shiftLeft(int index, int shift) {
for (int i = index; i < _size; i++) {
final int dest = i - shift;
_high[dest >> B1][dest & M1] = _high[i >> B1][i & M1];
}
}
// For inlining of default comparator.
private static boolean defaultEquals(Object o1, Object o2) {
return (o1 == null) ? (o2 == null) : (o1 == o2) || o1.equals(o2);
}
private static final long serialVersionUID = 1L;
}