mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
containers
This commit is contained in:
@@ -0,0 +1,852 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (c) 2001, Eric D. Friedman All Rights Reserved.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2.1 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
package com.intellij.util.containers;
|
||||
|
||||
import gnu.trove.HashFunctions;
|
||||
import gnu.trove.TIntProcedure;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* A resizable, array-backed list of int primitives.
|
||||
*
|
||||
* Created: Sat Dec 29 14:21:12 2001
|
||||
*
|
||||
* @author Eric D. Friedman
|
||||
* @version $Id: TIntArrayList.java,v 1.5 2004/09/24 09:11:15 cdr Exp $
|
||||
*/
|
||||
|
||||
public class ByteArrayList implements Cloneable {
|
||||
|
||||
/** the data of the list */
|
||||
protected transient byte[] _data;
|
||||
|
||||
/** the index after the last entry in the list */
|
||||
protected transient int _pos;
|
||||
|
||||
/** the default capacity for new lists */
|
||||
protected static final int DEFAULT_CAPACITY = 4;
|
||||
|
||||
/**
|
||||
* Creates a new <code>TIntArrayList</code> instance with the
|
||||
* default capacity.
|
||||
*/
|
||||
public ByteArrayList() {
|
||||
this(DEFAULT_CAPACITY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new <code>TIntArrayList</code> instance with the
|
||||
* specified capacity.
|
||||
*
|
||||
* @param capacity an <code>int</code> value
|
||||
*/
|
||||
public ByteArrayList(int capacity) {
|
||||
_data = new byte[capacity];
|
||||
_pos = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new <code>TIntArrayList</code> instance whose
|
||||
* capacity is the greater of the length of <tt>values</tt> and
|
||||
* DEFAULT_CAPACITY and whose initial contents are the specified
|
||||
* values.
|
||||
*
|
||||
* @param values an <code>int[]</code> value
|
||||
*/
|
||||
public ByteArrayList(byte[] values) {
|
||||
this(Math.max(values.length, DEFAULT_CAPACITY));
|
||||
add(values);
|
||||
}
|
||||
|
||||
// sizing
|
||||
|
||||
/**
|
||||
* Grow the internal array as needed to accomodate the specified
|
||||
* number of elements. The size of the array doubles on each
|
||||
* resize unless <tt>capacity</tt> requires more than twice the
|
||||
* current capacity.
|
||||
*
|
||||
* @param capacity an <code>int</code> value
|
||||
*/
|
||||
public void ensureCapacity(int capacity) {
|
||||
byte[] data = _data;
|
||||
if (capacity > data.length) {
|
||||
int newCap = Math.max(data.length < 100000 ? data.length << 1 : data.length * 4 / 3, capacity);
|
||||
byte[] tmp = new byte[newCap];
|
||||
System.arraycopy(data, 0, tmp, 0, data.length);
|
||||
_data = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of values in the list.
|
||||
*
|
||||
* @return the number of values in the list.
|
||||
*/
|
||||
public int size() {
|
||||
return _pos;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests whether this list contains any values.
|
||||
*
|
||||
* @return true if the list is empty.
|
||||
*/
|
||||
public boolean isEmpty() {
|
||||
return _pos == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sheds any excess capacity above and beyond the current size of
|
||||
* the list.
|
||||
*/
|
||||
public void trimToSize() {
|
||||
if (_data.length > size()) {
|
||||
byte[] tmp = new byte[size()];
|
||||
toNativeArray(tmp, 0, tmp.length);
|
||||
_data = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
// modifying
|
||||
|
||||
/**
|
||||
* Adds <tt>val</tt> to the end of the list, growing as needed.
|
||||
*
|
||||
* @param val an <code>int</code> value
|
||||
*/
|
||||
public void add(byte val) {
|
||||
ensureCapacity(_pos + 1);
|
||||
_data[_pos++] = val;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the values in the array <tt>vals</tt> to the end of the
|
||||
* list, in order.
|
||||
*
|
||||
* @param vals an <code>int[]</code> value
|
||||
*/
|
||||
public void add(byte[] vals) {
|
||||
add(vals, 0, vals.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a subset of the values in the array <tt>vals</tt> to the
|
||||
* end of the list, in order.
|
||||
*
|
||||
* @param vals an <code>int[]</code> value
|
||||
* @param offset the offset at which to start copying
|
||||
* @param length the number of values to copy.
|
||||
*/
|
||||
public void add(byte[] vals, int offset, int length) {
|
||||
ensureCapacity(_pos + length);
|
||||
System.arraycopy(vals, offset, _data, _pos, length);
|
||||
_pos += length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts <tt>value</tt> into the list at <tt>offset</tt>. All
|
||||
* values including and to the right of <tt>offset</tt> are shifted
|
||||
* to the right.
|
||||
*
|
||||
* @param offset an <code>int</code> value
|
||||
* @param value an <code>int</code> value
|
||||
*/
|
||||
public void insert(int offset, byte value) {
|
||||
if (offset == _pos) {
|
||||
add(value);
|
||||
return;
|
||||
}
|
||||
ensureCapacity(_pos + 1);
|
||||
// shift right
|
||||
System.arraycopy(_data, offset, _data, offset + 1, _pos - offset);
|
||||
// insert
|
||||
_data[offset] = value;
|
||||
_pos++;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts the array of <tt>values</tt> into the list at
|
||||
* <tt>offset</tt>. All values including and to the right of
|
||||
* <tt>offset</tt> are shifted to the right.
|
||||
*
|
||||
* @param offset an <code>int</code> value
|
||||
* @param values an <code>int[]</code> value
|
||||
*/
|
||||
public void insert(int offset, byte[] values) {
|
||||
insert(offset, values, 0, values.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts a slice of the array of <tt>values</tt> into the list
|
||||
* at <tt>offset</tt>. All values including and to the right of
|
||||
* <tt>offset</tt> are shifted to the right.
|
||||
*
|
||||
* @param offset an <code>int</code> value
|
||||
* @param values an <code>int[]</code> value
|
||||
* @param valOffset the offset in the values array at which to
|
||||
* start copying.
|
||||
* @param len the number of values to copy from the values array
|
||||
*/
|
||||
public void insert(int offset, byte[] values, int valOffset, int len) {
|
||||
if (offset == _pos) {
|
||||
add(values, valOffset, len);
|
||||
return;
|
||||
}
|
||||
|
||||
ensureCapacity(_pos + len);
|
||||
// shift right
|
||||
System.arraycopy(_data, offset, _data, offset + len, _pos - offset);
|
||||
// insert
|
||||
System.arraycopy(values, valOffset, _data, offset, len);
|
||||
_pos += len;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value at the specified offset.
|
||||
*
|
||||
* @param offset an <code>int</code> value
|
||||
* @return an <code>int</code> value
|
||||
*/
|
||||
public byte get(int offset) {
|
||||
if (offset >= _pos) {
|
||||
throw new ArrayIndexOutOfBoundsException(offset);
|
||||
}
|
||||
return _data[offset];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value at the specified offset without doing any
|
||||
* bounds checking.
|
||||
*
|
||||
* @param offset an <code>int</code> value
|
||||
* @return an <code>int</code> value
|
||||
*/
|
||||
public byte getQuick(int offset) {
|
||||
return _data[offset];
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value at the specified offset.
|
||||
*
|
||||
* @param offset an <code>int</code> value
|
||||
* @param val an <code>int</code> value
|
||||
*/
|
||||
public void set(int offset, byte val) {
|
||||
if (offset < 0 || offset >= _pos) {
|
||||
throw new ArrayIndexOutOfBoundsException(offset);
|
||||
}
|
||||
_data[offset] = val;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value at the specified offset and returns the
|
||||
* previously stored value.
|
||||
*
|
||||
* @param offset an <code>int</code> value
|
||||
* @param val an <code>int</code> value
|
||||
* @return the value previously stored at offset.
|
||||
*/
|
||||
public byte getSet(int offset, byte val) {
|
||||
if (offset < 0 || offset >= _pos) {
|
||||
throw new ArrayIndexOutOfBoundsException(offset);
|
||||
}
|
||||
byte old = _data[offset];
|
||||
_data[offset] = val;
|
||||
return old;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace the values in the list starting at <tt>offset</tt> with
|
||||
* the contents of the <tt>values</tt> array.
|
||||
*
|
||||
* @param offset the first offset to replace
|
||||
* @param values the source of the new values
|
||||
*/
|
||||
public void set(int offset, byte[] values) {
|
||||
set(offset, values, 0, values.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace the values in the list starting at <tt>offset</tt> with
|
||||
* <tt>length</tt> values from the <tt>values</tt> array, starting
|
||||
* at valOffset.
|
||||
*
|
||||
* @param offset the first offset to replace
|
||||
* @param values the source of the new values
|
||||
* @param valOffset the first value to copy from the values array
|
||||
* @param length the number of values to copy
|
||||
*/
|
||||
public void set(int offset, byte[] values, int valOffset, int length) {
|
||||
if (offset < 0 || offset + length > _pos) {
|
||||
throw new ArrayIndexOutOfBoundsException(offset);
|
||||
}
|
||||
System.arraycopy(_data, offset, values, valOffset, length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value at the specified offset without doing any bounds
|
||||
* checking.
|
||||
*
|
||||
* @param offset an <code>int</code> value
|
||||
* @param val an <code>int</code> value
|
||||
*/
|
||||
public void setQuick(int offset, byte val) {
|
||||
_data[offset] = val;
|
||||
}
|
||||
|
||||
/**
|
||||
* Flushes the internal state of the list, resetting the capacity
|
||||
* to the default.
|
||||
*/
|
||||
public void clear() {
|
||||
clear(DEFAULT_CAPACITY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Flushes the internal state of the list, setting the capacity of
|
||||
* the empty list to <tt>capacity</tt>.
|
||||
*
|
||||
* @param capacity an <code>int</code> value
|
||||
*/
|
||||
public void clear(int capacity) {
|
||||
_data = new byte[capacity];
|
||||
_pos = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the size of the list to 0, but does not change its
|
||||
* capacity. This method can be used as an alternative to the
|
||||
* {@link #clear clear} method if you want to recyle a list without
|
||||
* allocating new backing arrays.
|
||||
*
|
||||
* @see #clear
|
||||
*/
|
||||
public void reset() {
|
||||
_pos = 0;
|
||||
fill((byte)0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the size of the list to 0, but does not change its
|
||||
* capacity. This method can be used as an alternative to the
|
||||
* {@link #clear clear} method if you want to recyle a list
|
||||
* without allocating new backing arrays. This method differs
|
||||
* from {@link #reset reset} in that it does not clear the old
|
||||
* values in the backing array. Thus, it is possible for {@link
|
||||
* #getQuick getQuick} to return stale data if this method is used
|
||||
* and the caller is careless about bounds checking.
|
||||
*
|
||||
* @see #reset
|
||||
* @see #clear
|
||||
* @see #getQuick
|
||||
*/
|
||||
public void resetQuick() {
|
||||
_pos = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the value at <tt>offset</tt> from the list.
|
||||
*
|
||||
* @param offset an <code>int</code> value
|
||||
* @return the value previously stored at offset.
|
||||
*/
|
||||
public byte remove(int offset) {
|
||||
byte old = get(offset);
|
||||
remove(offset, 1);
|
||||
return old;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes <tt>length</tt> values from the list, starting at
|
||||
* <tt>offset</tt>
|
||||
*
|
||||
* @param offset an <code>int</code> value
|
||||
* @param length an <code>int</code> value
|
||||
*/
|
||||
public void remove(int offset, int length) {
|
||||
if (offset < 0 || offset >= _pos) {
|
||||
throw new ArrayIndexOutOfBoundsException(offset);
|
||||
}
|
||||
|
||||
if (offset == 0) {
|
||||
// data at the front
|
||||
System.arraycopy(_data, length, _data, 0, _pos - length);
|
||||
} else if (_pos - length == offset) {
|
||||
// no copy to make, decrementing pos "deletes" values at
|
||||
// the end
|
||||
} else {
|
||||
// data in the middle
|
||||
System.arraycopy(_data, offset + length,
|
||||
_data, offset, _pos - (offset + length));
|
||||
}
|
||||
_pos -= length;
|
||||
// no need to clear old values beyond _pos, because this is a
|
||||
// primitive collection and 0 takes as much room as any other
|
||||
// value
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Reverse the order of the elements in the list.
|
||||
*/
|
||||
public void reverse() {
|
||||
reverse(0, _pos);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the order of the elements in the range of the list.
|
||||
*
|
||||
* @param from the inclusive index at which to start reversing
|
||||
* @param to the exclusive index at which to stop reversing
|
||||
*/
|
||||
public void reverse(int from, int to) {
|
||||
if (from == to) {
|
||||
return; // nothing to do
|
||||
}
|
||||
if (from > to) {
|
||||
throw new IllegalArgumentException("from cannot be greater than to");
|
||||
}
|
||||
for (int i = from, j = to - 1; i < j; i++, j--) {
|
||||
swap(i, j);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Shuffle the elements of the list using the specified random
|
||||
* number generator.
|
||||
*
|
||||
* @param rand a <code>Random</code> value
|
||||
*/
|
||||
public void shuffle(Random rand) {
|
||||
for (int i = _pos; i-- > 1;) {
|
||||
swap(i, rand.nextInt(i));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Swap the values at offsets <tt>i</tt> and <tt>j</tt>.
|
||||
*
|
||||
* @param i an offset into the data array
|
||||
* @param j an offset into the data array
|
||||
*/
|
||||
private final void swap(int i, int j) {
|
||||
byte tmp = _data[i];
|
||||
_data[i] = _data[j];
|
||||
_data[j] = tmp;
|
||||
}
|
||||
|
||||
// copying
|
||||
|
||||
/**
|
||||
* Returns a clone of this list. Since this is a primitive
|
||||
* collection, this will be a deep clone.
|
||||
*
|
||||
* @return a deep clone of the list.
|
||||
*/
|
||||
public Object clone() {
|
||||
ByteArrayList clone = null;
|
||||
try {
|
||||
clone = (ByteArrayList)super.clone();
|
||||
clone._data = (byte[])_data.clone();
|
||||
} catch (CloneNotSupportedException e) {
|
||||
// it's supported
|
||||
} // end of try-catch
|
||||
return clone;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies the contents of the list into a native array.
|
||||
*
|
||||
* @return an <code>int[]</code> value
|
||||
*/
|
||||
public byte[] toNativeArray() {
|
||||
return toNativeArray(0, _pos);
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies a slice of the list into a native array.
|
||||
*
|
||||
* @param offset the offset at which to start copying
|
||||
* @param len the number of values to copy.
|
||||
* @return an <code>int[]</code> value
|
||||
*/
|
||||
public byte[] toNativeArray(int offset, int len) {
|
||||
byte[] rv = new byte[len];
|
||||
toNativeArray(rv, offset, len);
|
||||
return rv;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies a slice of the list into a native array.
|
||||
*
|
||||
* @param dest the array to copy into.
|
||||
* @param offset the offset of the first value to copy
|
||||
* @param len the number of values to copy.
|
||||
*/
|
||||
public void toNativeArray(byte[] dest, int offset, int len) {
|
||||
if (len == 0) {
|
||||
return; // nothing to copy
|
||||
}
|
||||
if (offset < 0 || offset >= _pos) {
|
||||
throw new ArrayIndexOutOfBoundsException(offset);
|
||||
}
|
||||
System.arraycopy(_data, offset, dest, 0, len);
|
||||
}
|
||||
|
||||
// comparing
|
||||
|
||||
/**
|
||||
* Compares this list to another list, value by value.
|
||||
*
|
||||
* @param other the object to compare against
|
||||
* @return true if other is a TIntArrayList and has exactly the
|
||||
* same values.
|
||||
*/
|
||||
public boolean equals(Object other) {
|
||||
if (other == this) {
|
||||
return true;
|
||||
} else if (other instanceof ByteArrayList) {
|
||||
ByteArrayList that = (ByteArrayList)other;
|
||||
if (that.size() != this.size()) {
|
||||
return false;
|
||||
} else {
|
||||
for (int i = _pos; i-- > 0;) {
|
||||
if (this._data[i] != that._data[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
int h = 0;
|
||||
for (int i = _pos; i-- > 0;) {
|
||||
h += HashFunctions.hash(_data[i]);
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
// procedures
|
||||
|
||||
/**
|
||||
* Applies the procedure to each value in the list in ascending
|
||||
* (front to back) order.
|
||||
*
|
||||
* @param procedure a <code>TIntProcedure</code> value
|
||||
* @return true if the procedure did not terminate prematurely.
|
||||
*/
|
||||
public boolean forEach(TIntProcedure procedure) {
|
||||
for (int i = 0; i < _pos; i++) {
|
||||
if (! procedure.execute(_data[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the procedure to each value in the list in descending
|
||||
* (back to front) order.
|
||||
*
|
||||
* @param procedure a <code>TIntProcedure</code> value
|
||||
* @return true if the procedure did not terminate prematurely.
|
||||
*/
|
||||
public boolean forEachDescending(TIntProcedure procedure) {
|
||||
for (int i = _pos; i-- > 0;) {
|
||||
if (! procedure.execute(_data[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// sorting
|
||||
|
||||
/**
|
||||
* Sort the values in the list (ascending) using the Sun quicksort
|
||||
* implementation.
|
||||
*
|
||||
* @see java.util.Arrays#sort
|
||||
*/
|
||||
public void sort() {
|
||||
Arrays.sort(_data, 0, _pos);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort a slice of the list (ascending) using the Sun quicksort
|
||||
* implementation.
|
||||
*
|
||||
* @param fromIndex the index at which to start sorting (inclusive)
|
||||
* @param toIndex the index at which to stop sorting (exclusive)
|
||||
* @see java.util.Arrays#sort
|
||||
*/
|
||||
public void sort(int fromIndex, int toIndex) {
|
||||
Arrays.sort(_data, fromIndex, toIndex);
|
||||
}
|
||||
|
||||
// filling
|
||||
|
||||
/**
|
||||
* Fills every slot in the list with the specified value.
|
||||
*
|
||||
* @param val the value to use when filling
|
||||
*/
|
||||
public void fill(byte val) {
|
||||
Arrays.fill(_data, 0, _pos, val);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fills a range in the list with the specified value.
|
||||
*
|
||||
* @param fromIndex the offset at which to start filling (inclusive)
|
||||
* @param toIndex the offset at which to stop filling (exclusive)
|
||||
* @param val the value to use when filling
|
||||
*/
|
||||
public void fill(int fromIndex, int toIndex, byte val) {
|
||||
if (toIndex > _pos) {
|
||||
ensureCapacity(toIndex);
|
||||
_pos = toIndex;
|
||||
}
|
||||
Arrays.fill(_data, fromIndex, toIndex, val);
|
||||
}
|
||||
|
||||
// searching
|
||||
|
||||
/**
|
||||
* Performs a binary search for <tt>value</tt> in the entire list.
|
||||
* Note that you <b>must</b> {@link #sort sort} the list before
|
||||
* doing a search.
|
||||
*
|
||||
* @param value the value to search for
|
||||
* @return the absolute offset in the list of the value, or its
|
||||
* negative insertion point into the sorted list.
|
||||
*/
|
||||
public int binarySearch(byte value) {
|
||||
return binarySearch(value, 0, _pos);
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a binary search for <tt>value</tt> in the specified
|
||||
* range. Note that you <b>must</b> {@link #sort sort} the list
|
||||
* or the range before doing a search.
|
||||
*
|
||||
* @param value the value to search for
|
||||
* @param fromIndex the lower boundary of the range (inclusive)
|
||||
* @param toIndex the upper boundary of the range (exclusive)
|
||||
* @return the absolute offset in the list of the value, or its
|
||||
* negative insertion point into the sorted list.
|
||||
*/
|
||||
public int binarySearch(byte value, int fromIndex, int toIndex) {
|
||||
if (fromIndex < 0) {
|
||||
throw new ArrayIndexOutOfBoundsException(fromIndex);
|
||||
}
|
||||
if (toIndex > _pos) {
|
||||
throw new ArrayIndexOutOfBoundsException(toIndex);
|
||||
}
|
||||
|
||||
int low = fromIndex;
|
||||
int high = toIndex - 1;
|
||||
|
||||
while (low <= high) {
|
||||
int mid = (low + high) >> 1;
|
||||
byte midVal = _data[mid];
|
||||
|
||||
if (midVal < value) {
|
||||
low = mid + 1;
|
||||
} else if (midVal > value) {
|
||||
high = mid - 1;
|
||||
} else {
|
||||
return mid; // value found
|
||||
}
|
||||
}
|
||||
return -(low + 1); // value not found.
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches the list front to back for the index of
|
||||
* <tt>value</tt>.
|
||||
*
|
||||
* @param value an <code>int</code> value
|
||||
* @return the first offset of the value, or -1 if it is not in
|
||||
* the list.
|
||||
* @see #binarySearch for faster searches on sorted lists
|
||||
*/
|
||||
public int indexOf(byte value) {
|
||||
return indexOf(0, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches the list front to back for the index of
|
||||
* <tt>value</tt>, starting at <tt>offset</tt>.
|
||||
*
|
||||
* @param offset the offset at which to start the linear search
|
||||
* (inclusive)
|
||||
* @param value an <code>int</code> value
|
||||
* @return the first offset of the value, or -1 if it is not in
|
||||
* the list.
|
||||
* @see #binarySearch for faster searches on sorted lists
|
||||
*/
|
||||
public int indexOf(int offset, byte value) {
|
||||
for (int i = offset; i < _pos; i++) {
|
||||
if (_data[i] == value) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches the list back to front for the last index of
|
||||
* <tt>value</tt>.
|
||||
*
|
||||
* @param value an <code>int</code> value
|
||||
* @return the last offset of the value, or -1 if it is not in
|
||||
* the list.
|
||||
* @see #binarySearch for faster searches on sorted lists
|
||||
*/
|
||||
public int lastIndexOf(byte value) {
|
||||
return lastIndexOf(_pos, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches the list back to front for the last index of
|
||||
* <tt>value</tt>, starting at <tt>offset</tt>.
|
||||
*
|
||||
* @param offset the offset at which to start the linear search
|
||||
* (exclusive)
|
||||
* @param value an <code>int</code> value
|
||||
* @return the last offset of the value, or -1 if it is not in
|
||||
* the list.
|
||||
* @see #binarySearch for faster searches on sorted lists
|
||||
*/
|
||||
public int lastIndexOf(int offset, byte value) {
|
||||
for (int i = offset; i-- > 0;) {
|
||||
if (_data[i] == value) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches the list for <tt>value</tt>
|
||||
*
|
||||
* @param value an <code>int</code> value
|
||||
* @return true if value is in the list.
|
||||
*/
|
||||
public boolean contains(byte value) {
|
||||
return lastIndexOf(value) >= 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches the list for values satisfying <tt>condition</tt> in
|
||||
* the manner of the *nix <tt>grep</tt> utility.
|
||||
*
|
||||
* @param condition a condition to apply to each element in the list
|
||||
* @return a list of values which match the condition.
|
||||
*/
|
||||
public ByteArrayList grep(TIntProcedure condition) {
|
||||
ByteArrayList list = new ByteArrayList();
|
||||
for (int i = 0; i < _pos; i++) {
|
||||
if (condition.execute(_data[i])) {
|
||||
list.add(_data[i]);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches the list for values which do <b>not</b> satisfy
|
||||
* <tt>condition</tt>. This is akin to *nix <code>grep -v</code>.
|
||||
*
|
||||
* @param condition a condition to apply to each element in the list
|
||||
* @return a list of values which do not match the condition.
|
||||
*/
|
||||
public ByteArrayList inverseGrep(TIntProcedure condition) {
|
||||
ByteArrayList list = new ByteArrayList();
|
||||
for (int i = 0; i < _pos; i++) {
|
||||
if (! condition.execute(_data[i])) {
|
||||
list.add(_data[i]);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the maximum value in the list.
|
||||
*
|
||||
* @return the largest value in the list.
|
||||
* @exception IllegalStateException if the list is empty
|
||||
*/
|
||||
public int max() {
|
||||
if (size() == 0) {
|
||||
throw new IllegalStateException("cannot find maximum of an empty list");
|
||||
}
|
||||
int max = _data[_pos - 1];
|
||||
for (int i = _pos - 1; i-- > 0;) {
|
||||
max = Math.max(max, _data[_pos]);
|
||||
}
|
||||
return max;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the minimum value in the list.
|
||||
*
|
||||
* @return the smallest value in the list.
|
||||
* @exception IllegalStateException if the list is empty
|
||||
*/
|
||||
public int min() {
|
||||
if (size() == 0) {
|
||||
throw new IllegalStateException("cannot find minimum of an empty list");
|
||||
}
|
||||
int min = _data[_pos - 1];
|
||||
for (int i = _pos - 1; i-- > 0;) {
|
||||
min = Math.min(min, _data[_pos]);
|
||||
}
|
||||
return min;
|
||||
}
|
||||
|
||||
// stringification
|
||||
|
||||
/**
|
||||
* Returns a String representation of the list, front to back.
|
||||
*
|
||||
* @return a <code>String</code> value
|
||||
*/
|
||||
public String toString() {
|
||||
final StringBuffer buf = new StringBuffer("{");
|
||||
forEach(new TIntProcedure() {
|
||||
public boolean execute(int val) {
|
||||
buf.append(val);
|
||||
buf.append(", ");
|
||||
return true;
|
||||
}
|
||||
});
|
||||
buf.append("}");
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
} // TIntArrayList
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2000-2012 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.util.containers;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* methods adapted from java.util.concurrent.ConcurrentMap to integer keys
|
||||
* @see java.util.concurrent.ConcurrentMap
|
||||
*/
|
||||
public interface ConcurrentIntObjectMap<V> {
|
||||
// concurrency related methods
|
||||
|
||||
/**
|
||||
* @return written value
|
||||
*/
|
||||
@NotNull
|
||||
V cacheOrGet(int key, @NotNull V value);
|
||||
boolean remove(int key, @NotNull V value);
|
||||
boolean replace(int key, @NotNull V oldValue, @NotNull V newValue);
|
||||
|
||||
// regular Map methods
|
||||
V put(int key, @NotNull V value);
|
||||
V get(int key);
|
||||
V remove(int key);
|
||||
boolean containsKey(int key);
|
||||
void clear();
|
||||
@NotNull
|
||||
Iterable<StripedLockIntObjectConcurrentHashMap.IntEntry<V>> entries();
|
||||
}
|
||||
+153
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
* Copyright 2000-2012 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.intellij.util.containers;
|
||||
|
||||
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.lang.ref.ReferenceQueue;
|
||||
import java.util.Iterator;
|
||||
|
||||
abstract class ConcurrentRefValueIntObjectHashMap<V> implements ConcurrentIntObjectMap<V> {
|
||||
private final StripedLockIntObjectConcurrentHashMap<IntReference<V>> myMap = new StripedLockIntObjectConcurrentHashMap<IntReference<V>>();
|
||||
private final ReferenceQueue<V> myQueue = new ReferenceQueue<V>();
|
||||
|
||||
protected abstract IntReference<V> createReference(int key, @NotNull V value, ReferenceQueue<V> queue);
|
||||
|
||||
protected interface IntReference<V> {
|
||||
int getKey();
|
||||
V get();
|
||||
}
|
||||
|
||||
void processQueue() {
|
||||
while(true){
|
||||
IntReference ref = (IntReference)myQueue.poll();
|
||||
if (ref == null) {
|
||||
return;
|
||||
}
|
||||
int key = ref.getKey();
|
||||
myMap.remove(key);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public V cacheOrGet(int key, @NotNull V value) {
|
||||
processQueue();
|
||||
IntReference<V> ref = myMap.putIfAbsent(key, createReference(key, value, myQueue));
|
||||
V v = ref == null ? null : ref.get();
|
||||
return v == null ? value : v;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean remove(int key, @NotNull V value) {
|
||||
processQueue();
|
||||
return myMap.remove(key, createReference(key, value, myQueue));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean replace(int key, @NotNull V oldValue, @NotNull V newValue) {
|
||||
processQueue();
|
||||
return myMap.replace(key, createReference(key, oldValue,myQueue), createReference(key, newValue,myQueue));
|
||||
}
|
||||
|
||||
@Override
|
||||
public V put(int key, @NotNull V value) {
|
||||
processQueue();
|
||||
IntReference<V> ref = myMap.put(key, createReference(key, value, myQueue));
|
||||
return ref == null ? null : ref.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public V get(int key) {
|
||||
IntReference<V> ref = myMap.get(key);
|
||||
return ref == null ? null : ref.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public V remove(int key) {
|
||||
processQueue();
|
||||
IntReference<V> ref = myMap.remove(key);
|
||||
return ref == null ? null : ref.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsKey(int key) {
|
||||
return myMap.containsKey(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
myMap.clear();
|
||||
processQueue();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Iterable<StripedLockIntObjectConcurrentHashMap.IntEntry<V>> entries() {
|
||||
final Iterator<StripedLockIntObjectConcurrentHashMap.IntEntry<IntReference<V>>> entryIterator = myMap.entries().iterator();
|
||||
return new Iterable<StripedLockIntObjectConcurrentHashMap.IntEntry<V>>() {
|
||||
@Override
|
||||
public Iterator<StripedLockIntObjectConcurrentHashMap.IntEntry<V>> iterator() {
|
||||
return new Iterator<StripedLockIntObjectConcurrentHashMap.IntEntry<V>>() {
|
||||
StripedLockIntObjectConcurrentHashMap.IntEntry<V> next = nextAliveEntry();
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return next != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public StripedLockIntObjectConcurrentHashMap.IntEntry<V> next() {
|
||||
StripedLockIntObjectConcurrentHashMap.IntEntry<V> result = next;
|
||||
next = nextAliveEntry();
|
||||
return result;
|
||||
}
|
||||
|
||||
private StripedLockIntObjectConcurrentHashMap.IntEntry<V> nextAliveEntry() {
|
||||
while (entryIterator.hasNext()) {
|
||||
StripedLockIntObjectConcurrentHashMap.IntEntry<IntReference<V>> entry = entryIterator.next();
|
||||
final V v = entry.getValue().get();
|
||||
if (v == null) {
|
||||
continue;
|
||||
}
|
||||
final int key = entry.getKey();
|
||||
return new StripedLockIntObjectConcurrentHashMap.IntEntry<V>() {
|
||||
@Override
|
||||
public int getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public V getValue() {
|
||||
return v;
|
||||
}
|
||||
};
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
throw new IncorrectOperationException("not implemented");
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright 2000-2012 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.intellij.util.containers;
|
||||
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.lang.ref.ReferenceQueue;
|
||||
import java.lang.ref.SoftReference;
|
||||
|
||||
public class ConcurrentSoftValueIntObjectHashMap<V> extends ConcurrentRefValueIntObjectHashMap<V> {
|
||||
private static class MyRef<V> extends SoftReference<V> implements IntReference<V> {
|
||||
private final int hash;
|
||||
private final int key;
|
||||
|
||||
MyRef(int key, @NotNull V referent, ReferenceQueue<V> queue) {
|
||||
super(referent, queue);
|
||||
this.key = key;
|
||||
hash = referent.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return hash;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
V v = get();
|
||||
return obj instanceof MyRef && ((MyRef)obj).hash == hash && v != null && v.equals(((MyRef)obj).get());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getKey() {
|
||||
return key;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IntReference<V> createReference(int key, @NotNull V value, ReferenceQueue<V> queue) {
|
||||
return new MyRef<V>(key, value, queue);
|
||||
}
|
||||
}
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright 2000-2012 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.intellij.util.containers;
|
||||
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.lang.ref.ReferenceQueue;
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
public class ConcurrentWeakValueIntObjectHashMap<V> extends ConcurrentRefValueIntObjectHashMap<V> {
|
||||
private static class MyRef<V> extends WeakReference<V> implements IntReference<V> {
|
||||
private final int hash;
|
||||
private final int key;
|
||||
|
||||
MyRef(int key, @NotNull V referent, ReferenceQueue<V> queue) {
|
||||
super(referent, queue);
|
||||
this.key = key;
|
||||
hash = referent.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return hash;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
V v = get();
|
||||
return obj instanceof MyRef && ((MyRef)obj).hash == hash && v != null && v.equals(((MyRef)obj).get());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getKey() {
|
||||
return key;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IntReference<V> createReference(int key, @NotNull V value, ReferenceQueue<V> queue) {
|
||||
return new MyRef<V>(key, value, queue);
|
||||
}
|
||||
}
|
||||
@@ -50,6 +50,20 @@ public class IntArrayList implements Cloneable {
|
||||
System.arraycopy(oldData, 0, myData, 0, mySize);
|
||||
}
|
||||
}
|
||||
public void fill(int fromIndex, int toIndex, int value) {
|
||||
if (toIndex > mySize) {
|
||||
ensureCapacity(toIndex);
|
||||
mySize = toIndex;
|
||||
}
|
||||
Arrays.fill(myData, fromIndex, toIndex, value);
|
||||
}
|
||||
|
||||
public void add(int[] values) {
|
||||
int length = values.length;
|
||||
ensureCapacity(mySize + length);
|
||||
System.arraycopy(values, 0, myData, mySize, length);
|
||||
mySize += length;
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return mySize;
|
||||
@@ -105,11 +119,19 @@ public class IntArrayList implements Cloneable {
|
||||
|
||||
return a;
|
||||
}
|
||||
public int[] toArray(int startIndex, int length) {
|
||||
int[] result = new int[length];
|
||||
System.arraycopy(myData, startIndex, result, 0, length);
|
||||
return result;
|
||||
}
|
||||
|
||||
public int get(int index) {
|
||||
checkRange(index);
|
||||
return myData[index];
|
||||
}
|
||||
public int getQuick(int index) {
|
||||
return myData[index];
|
||||
}
|
||||
|
||||
public int set(int index, int element) {
|
||||
checkRange(index);
|
||||
@@ -118,6 +140,9 @@ public class IntArrayList implements Cloneable {
|
||||
myData[index] = element;
|
||||
return oldValue;
|
||||
}
|
||||
public void setQuick(int index, int element) {
|
||||
myData[index] = element;
|
||||
}
|
||||
|
||||
public void add(int o) {
|
||||
ensureCapacity(mySize + 1);
|
||||
|
||||
+52
-38
@@ -16,21 +16,22 @@
|
||||
|
||||
package com.intellij.util.containers;
|
||||
|
||||
import gnu.trove.THashSet;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Iterator;
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
/** similar to java.util.ConcurrentHashMap except:
|
||||
keys are ints
|
||||
conserved as much memory as possible by
|
||||
-- using only one Segment
|
||||
-- eliminating unnecessary fields
|
||||
-- using one of 256 ReentrantLock for Segment staticly preallocated in StripedReentrantLocks
|
||||
-- using one of 256 ReentrantLock for Segment statically pre-allocated in {@link StripedReentrantLocks}
|
||||
added hashing strategy argument
|
||||
made not Serializable
|
||||
*/
|
||||
public class StripedLockIntObjectConcurrentHashMap<V> {
|
||||
public class StripedLockIntObjectConcurrentHashMap<V> implements ConcurrentIntObjectMap<V> {
|
||||
/* ---------------- Constants -------------- */
|
||||
|
||||
/**
|
||||
@@ -145,6 +146,7 @@ public class StripedLockIntObjectConcurrentHashMap<V> {
|
||||
* @throws NullPointerException if the key or value is
|
||||
* <tt>null</tt>.
|
||||
*/
|
||||
@Override
|
||||
public V put(int key, @NotNull V value) {
|
||||
return put(key, value, false);
|
||||
}
|
||||
@@ -185,19 +187,22 @@ public class StripedLockIntObjectConcurrentHashMap<V> {
|
||||
* @throws NullPointerException if the key is
|
||||
* <tt>null</tt>.
|
||||
*/
|
||||
@Override
|
||||
public V remove(int key) {
|
||||
return remove(key, null);
|
||||
return doRemove(key, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean remove(int key, @NotNull V value) {
|
||||
return doRemove(key, value) != null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public V cacheOrGet(int key, @NotNull V value) {
|
||||
V prev = putIfAbsent(key, value);
|
||||
return prev == null ? value : prev;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an enumeration of the values in this table.
|
||||
@@ -212,13 +217,11 @@ public class StripedLockIntObjectConcurrentHashMap<V> {
|
||||
/* ---------------- Iterator Support -------------- */
|
||||
|
||||
private class HashIterator {
|
||||
private int nextTableIndex;
|
||||
private IntHashEntry[] currentTable;
|
||||
private int nextTableIndex = table.length - 1;
|
||||
private IntHashEntry<V> nextEntry;
|
||||
private IntHashEntry<V> lastReturned;
|
||||
|
||||
private HashIterator() {
|
||||
nextTableIndex = -1;
|
||||
advance();
|
||||
}
|
||||
|
||||
@@ -232,21 +235,10 @@ public class StripedLockIntObjectConcurrentHashMap<V> {
|
||||
}
|
||||
|
||||
while (nextTableIndex >= 0) {
|
||||
if ((nextEntry = (IntHashEntry<V>)currentTable[nextTableIndex--]) != null) {
|
||||
if ((nextEntry = (IntHashEntry<V>)table[nextTableIndex--]) != null) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
StripedLockIntObjectConcurrentHashMap seg = StripedLockIntObjectConcurrentHashMap.this;
|
||||
if (seg.count != 0) {
|
||||
currentTable = seg.table;
|
||||
for (int j = currentTable.length - 1; j >= 0; --j) {
|
||||
if ((nextEntry = (IntHashEntry<V>)currentTable[j]) != null) {
|
||||
nextTableIndex = j - 1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasNext() {
|
||||
@@ -289,15 +281,33 @@ public class StripedLockIntObjectConcurrentHashMap<V> {
|
||||
}
|
||||
|
||||
|
||||
public Collection<IntEntry<V>> entries() {
|
||||
HashIterator iterator = new HashIterator();
|
||||
Set<IntEntry<V>> result = new THashSet<IntEntry<V>>();
|
||||
while (iterator.hasNext()) {
|
||||
IntHashEntry<V> ie = iterator.nextEntry;
|
||||
SimpleEntry<V> entry = new SimpleEntry<V>(ie.key, ie.value);
|
||||
result.add(entry);
|
||||
}
|
||||
return result;
|
||||
@Override
|
||||
@NotNull
|
||||
public Iterable<IntEntry<V>> entries() {
|
||||
return new Iterable<IntEntry<V>>() {
|
||||
@Override
|
||||
public Iterator<IntEntry<V>> iterator() {
|
||||
final HashIterator hashIterator = new HashIterator();
|
||||
return new Iterator<IntEntry<V>>() {
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return hashIterator.hasNext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public IntEntry<V> next() {
|
||||
IntHashEntry<V> ie = hashIterator.nextEntry;
|
||||
hashIterator.nextEntry();
|
||||
return new SimpleEntry<V>(ie.key, ie.value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
hashIterator.remove();
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -461,6 +471,7 @@ public class StripedLockIntObjectConcurrentHashMap<V> {
|
||||
|
||||
/* Specialized implementations of map methods */
|
||||
|
||||
@Override
|
||||
public V get(int key) {
|
||||
if (count != 0) { // read-volatile
|
||||
IntHashEntry<V> e = getFirst(key);
|
||||
@@ -478,6 +489,7 @@ public class StripedLockIntObjectConcurrentHashMap<V> {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsKey(int key) {
|
||||
if (count != 0) { // read-volatile
|
||||
IntHashEntry<V> e = getFirst(key);
|
||||
@@ -491,6 +503,7 @@ public class StripedLockIntObjectConcurrentHashMap<V> {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean replace(int key, @NotNull V oldValue, @NotNull V newValue) {
|
||||
lock();
|
||||
try {
|
||||
@@ -614,7 +627,7 @@ public class StripedLockIntObjectConcurrentHashMap<V> {
|
||||
/**
|
||||
* Remove; match on key only if value null, else match both.
|
||||
*/
|
||||
protected V remove(int key, Object value) {
|
||||
protected V doRemove(int key, V value) {
|
||||
lock();
|
||||
try {
|
||||
int c = count - 1;
|
||||
@@ -650,6 +663,7 @@ public class StripedLockIntObjectConcurrentHashMap<V> {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
if (count != 0) {
|
||||
lock();
|
||||
|
||||
Reference in New Issue
Block a user