Added a constructor that takes a Collection<Integer>. Widened and rearranged

the methods into a sane order.


git-svn-id: https://samskivert.googlecode.com/svn/trunk@2617 6335cc39-0255-0410-8fd6-9bcaacd3b74c
This commit is contained in:
samskivert
2009-08-20 21:53:59 +00:00
parent 1e530cd63d
commit a21bc48820
+191 -177
View File
@@ -29,8 +29,8 @@ import java.util.Iterator;
import java.util.NoSuchElementException; import java.util.NoSuchElementException;
/** /**
* Provides an {@link IntSet} implementation using a sorted array of * Provides an {@link IntSet} implementation using a sorted array of integers to maintain the
* integers to maintain the contents of the set. * contents of the set.
*/ */
public class ArrayIntSet extends AbstractSet<Integer> public class ArrayIntSet extends AbstractSet<Integer>
implements IntSet, Cloneable, Serializable implements IntSet, Cloneable, Serializable
@@ -41,22 +41,27 @@ public class ArrayIntSet extends AbstractSet<Integer>
public ArrayIntSet (int[] values) public ArrayIntSet (int[] values)
{ {
this(values.length); this(values.length);
_size = values.length; _size = _values.length;
System.arraycopy(values, 0, _values, 0, _size); System.arraycopy(values, 0, _values, 0, _size);
Arrays.sort(_values); Arrays.sort(_values);
removeDuplicates();
}
// remove duplicates /**
if (_size > 1) { * Construct an ArrayIntSet with the specified starting values.
int last = _values[0]; *
for (int ii = 1; ii < _size; ) { * @throws NullPointerException if the collection contains any null values.
if (_values[ii] == last) { // shift everything down 1 */
_size--; public ArrayIntSet (Collection<Integer> values)
System.arraycopy(_values, ii + 1, _values, ii, _size - ii); {
} else { this(values.size());
last = _values[ii++]; _size = values.size();
} Iterator<Integer> iter = values.iterator();
} for (int ii = 0; iter.hasNext(); ii++) {
_values[ii] = iter.next().intValue();
} }
Arrays.sort(_values);
removeDuplicates();
} }
/** /**
@@ -75,43 +80,140 @@ public class ArrayIntSet extends AbstractSet<Integer>
this(DEFAULT_CAPACITY); this(DEFAULT_CAPACITY);
} }
@Override /**
public int size () * Add all of the values in the supplied array to the set.
*
* @param values elements to be added to this set.
*
* @return <tt>true</tt> if this set did not already contain all of the specified elements.
*/
public boolean add (int[] values)
{ {
return _size; boolean modified = false;
int vlength = values.length;
for (int i = 0; i < vlength; i++) {
modified = (add(values[i]) || modified);
}
return modified;
} }
/** /**
* Returns the element at the specified index. Note that the elements * Removes all values in the supplied array from the set. Any values that are in the array but
* in the set are unordered and could change order after insertion or * not in the set are simply ignored.
* removal. This method is useful only for accessing elements of a *
* static set (and has the desirable property of allowing access to * @param values elements to be removed from the set.
* the values in this set without having to create integer objects). *
* @return <tt>true</tt> if this set contained any of the specified elements (which will have
* been removed).
*/
public boolean remove (int[] values)
{
boolean modified = false;
int vcount = values.length;
for (int i = 0; i < vcount; i++) {
modified = (remove(values[i]) || modified);
}
return modified;
}
/**
* Returns the element at the specified index. Note that the elements in the set are unordered
* and could change order after insertion or removal. This method is useful only for accessing
* elements of a static set (and has the desirable property of allowing access to the values in
* this set without having to create integer objects).
*/ */
public int get (int index) public int get (int index)
{ {
return _values[index]; return _values[index];
} }
@Override /**
public boolean isEmpty () * Serializes this int set into an array at the specified offset. The array must be large
* enough to hold all the integers in our set at the offset specified.
*
* @return the array passed in.
*/
public int[] toIntArray (int[] target, int offset)
{ {
return _size == 0; System.arraycopy(_values, 0, target, offset, _size);
return target;
} }
@Override /**
public boolean contains (Object o) * Creates an array of shorts from the contents of this set. Any values outside the range of a
* short will be truncated by way of a cast.
*/
public short[] toShortArray ()
{ {
return contains(((Integer)o).intValue()); short[] values = new short[_size];
for (int ii = 0; ii < _size; ii++) {
values[ii] = (short)_values[ii];
}
return values;
} }
// documentation inherited from interface // from interface IntSet
public boolean contains (int value) public boolean contains (int value)
{ {
return (binarySearch(value) >= 0); return (binarySearch(value) >= 0);
} }
// documentation inherited from interface IntSet // from interface IntSet
public boolean add (int value)
{
int index = binarySearch(value);
if (index >= 0) {
return false;
}
// convert the return value into the insertion point
index += 1;
index *= -1;
// expand the values array if necessary, leaving room for the newly added element
int valen = _values.length;
int[] source = _values;
if (valen == _size) {
_values = new int[Math.max(DEFAULT_CAPACITY, valen*2)];
System.arraycopy(source, 0, _values, 0, index);
}
// shift and insert
if (_size > index) {
System.arraycopy(source, index, _values, index+1, _size-index);
}
_values[index] = value;
// increment our size
_size += 1;
return true;
}
// from interface IntSet
public boolean remove (int value)
{
int index = binarySearch(value);
if (index >= 0) {
_size--;
if ((_values.length > DEFAULT_CAPACITY) && (_size < _values.length/8)) {
// if we're using less than 1/8 of our capacity, shrink by half
int[] newVals = new int[_values.length/2];
System.arraycopy(_values, 0, newVals, 0, index);
System.arraycopy(_values, index+1, newVals, index, _size-index);
_values = newVals;
} else {
// shift entries past the removed one downwards
System.arraycopy(_values, index+1, _values, index, _size-index);
_values[_size] = 0;
}
return true;
}
return false;
}
// from interface IntSet
public Interator interator () public Interator interator ()
{ {
return new Interator() { return new Interator() {
@@ -146,19 +248,7 @@ public class ArrayIntSet extends AbstractSet<Integer>
}; };
} }
@Override // from interface IntSet
public Iterator<Integer> iterator ()
{
return interator();
}
@Override
public Object[] toArray ()
{
return toArray(new Integer[_size]);
}
// documentation inherited from interface
public Integer[] toArray (Integer[] a) public Integer[] toArray (Integer[] a)
{ {
for (int i = 0; i < _size; i++) { for (int i = 0; i < _size; i++) {
@@ -167,7 +257,7 @@ public class ArrayIntSet extends AbstractSet<Integer>
return a; return a;
} }
// documentation inherited from interface // from interface IntSet
public int[] toIntArray () public int[] toIntArray ()
{ {
int[] values = new int[_size]; int[] values = new int[_size];
@@ -175,140 +265,37 @@ public class ArrayIntSet extends AbstractSet<Integer>
return values; return values;
} }
/** @Override // from AbstractSet<Integer>
* Serializes this int set into an array at the specified offset. The public int size ()
* array must be large enough to hold all the integers in our set at
* the offset specified.
*
* @return the array passed in.
*/
public int[] toIntArray (int[] target, int offset)
{ {
System.arraycopy(_values, 0, target, offset, _size); return _size;
return target;
} }
/** @Override // from AbstractSet<Integer>
* Creates an array of shorts from the contents of this set. Any public boolean isEmpty ()
* values outside the range of a short will be truncated by way of a
* cast.
*/
public short[] toShortArray ()
{ {
short[] values = new short[_size]; return _size == 0;
for (int ii = 0; ii < _size; ii++) {
values[ii] = (short)_values[ii];
}
return values;
} }
@Override @Override // from AbstractSet<Integer>
public boolean contains (Object o)
{
return contains(((Integer)o).intValue());
}
@Override // from AbstractSet<Integer>
public boolean add (Integer o) public boolean add (Integer o)
{ {
return add(o.intValue()); return add(o.intValue());
} }
// documentation inherited from interface @Override // from AbstractSet<Integer>
public boolean add (int value)
{
int index = binarySearch(value);
if (index >= 0) {
return false;
}
// convert the return value into the insertion point
index += 1;
index *= -1;
// expand the values array if necessary, leaving room for the
// newly added element
int valen = _values.length;
int[] source = _values;
if (valen == _size) {
_values = new int[Math.max(DEFAULT_CAPACITY, valen*2)];
System.arraycopy(source, 0, _values, 0, index);
}
// shift and insert
if (_size > index) {
System.arraycopy(source, index, _values, index+1, _size-index);
}
_values[index] = value;
// increment our size
_size += 1;
return true;
}
/**
* Add all of the values in the supplied array to the set.
*
* @param values elements to be added to this set.
*
* @return <tt>true</tt> if this set did not already contain all of
* the specified elements.
*/
public boolean add (int[] values)
{
boolean modified = false;
int vlength = values.length;
for (int i = 0; i < vlength; i++) {
modified = (add(values[i]) || modified);
}
return modified;
}
@Override
public boolean remove (Object o) public boolean remove (Object o)
{ {
return remove(((Integer)o).intValue()); return remove(((Integer)o).intValue());
} }
// documentation inherited from interface @Override // from AbstractSet<Integer>
public boolean remove (int value)
{
int index = binarySearch(value);
if (index >= 0) {
_size--;
if ((_values.length > DEFAULT_CAPACITY) &&
(_size < _values.length/8)) {
// if we're using less than 1/8 of our capacity, shrink by half
int[] newVals = new int[_values.length/2];
System.arraycopy(_values, 0, newVals, 0, index);
System.arraycopy(_values, index+1, newVals, index, _size-index);
_values = newVals;
} else {
// shift entries past the removed one downwards
System.arraycopy(_values, index+1, _values, index, _size-index);
_values[_size] = 0;
}
return true;
}
return false;
}
/**
* Removes all values in the supplied array from the set. Any values
* that are in the array but not in the set are simply ignored.
*
* @param values elements to be removed from the set.
*
* @return <tt>true</tt> if this set contained any of the specified
* elements (which will have been removed).
*/
public boolean remove (int[] values)
{
boolean modified = false;
int vcount = values.length;
for (int i = 0; i < vcount; i++) {
modified = (remove(values[i]) || modified);
}
return modified;
}
@Override
public boolean containsAll (Collection<?> c) public boolean containsAll (Collection<?> c)
{ {
if (c instanceof Interable) { if (c instanceof Interable) {
@@ -325,7 +312,7 @@ public class ArrayIntSet extends AbstractSet<Integer>
} }
} }
@Override @Override // from AbstractSet<Integer>
public boolean addAll (Collection<? extends Integer> c) public boolean addAll (Collection<? extends Integer> c)
{ {
if (c instanceof Interable) { if (c instanceof Interable) {
@@ -343,7 +330,7 @@ public class ArrayIntSet extends AbstractSet<Integer>
} }
} }
@Override @Override // from AbstractSet<Integer>
public boolean retainAll (Collection<?> c) public boolean retainAll (Collection<?> c)
{ {
if (c instanceof IntSet) { if (c instanceof IntSet) {
@@ -371,14 +358,26 @@ public class ArrayIntSet extends AbstractSet<Integer>
} }
} }
@Override @Override // from AbstractSet<Integer>
public Iterator<Integer> iterator ()
{
return interator();
}
@Override // from AbstractSet<Integer>
public Object[] toArray ()
{
return toArray(new Integer[_size]);
}
@Override // from AbstractSet<Integer>
public void clear () public void clear ()
{ {
Arrays.fill(_values, 0); Arrays.fill(_values, 0);
_size = 0; _size = 0;
} }
@Override @Override // from AbstractSet<Integer>
public boolean equals (Object o) public boolean equals (Object o)
{ {
// use an optimized equality test for another ArrayIntSet // use an optimized equality test for another ArrayIntSet
@@ -398,7 +397,7 @@ public class ArrayIntSet extends AbstractSet<Integer>
return super.equals(o); return super.equals(o);
} }
@Override @Override // from AbstractSet<Integer>
public int hashCode () public int hashCode ()
{ {
int hashCode = 0; int hashCode = 0;
@@ -408,7 +407,7 @@ public class ArrayIntSet extends AbstractSet<Integer>
return hashCode; return hashCode;
} }
@Override @Override // from AbstractSet<Integer>
public Object clone () public Object clone ()
{ {
try { try {
@@ -421,17 +420,16 @@ public class ArrayIntSet extends AbstractSet<Integer>
} }
} }
@Override @Override // from AbstractSet<Integer>
public String toString () public String toString ()
{ {
return StringUtil.toString(iterator()); return StringUtil.toString(iterator());
} }
/** /**
* Performs a binary search on our values array, looking for the * Performs a binary search on our values array, looking for the specified value. Swiped from
* specified value. Swiped from <code>java.util.Arrays</code> because * <code>java.util.Arrays</code> because those wankers didn't provide a means by which to
* those wankers didn't provide a means by which to perform a binary * perform a binary search on a subset of an array.
* search on a subset of an array.
*/ */
protected int binarySearch (int key) protected int binarySearch (int key)
{ {
@@ -454,6 +452,25 @@ public class ArrayIntSet extends AbstractSet<Integer>
return -(low + 1); // key not found. return -(low + 1); // key not found.
} }
/**
* Removes duplicates from our internal array. Only used by our constructors when initializing
* from a potentially duplicate-containing source array or collection.
*/
protected void removeDuplicates ()
{
if (_size > 1) {
int last = _values[0];
for (int ii = 1; ii < _size; ) {
if (_values[ii] == last) { // shift everything down 1
_size--;
System.arraycopy(_values, ii + 1, _values, ii, _size - ii);
} else {
last = _values[ii++];
}
}
}
}
/** An array containing the values in this set. */ /** An array containing the values in this set. */
protected int[] _values; protected int[] _values;
@@ -463,9 +480,6 @@ public class ArrayIntSet extends AbstractSet<Integer>
/** The default initial capacity of this set. */ /** The default initial capacity of this set. */
protected static final int DEFAULT_CAPACITY = 16; protected static final int DEFAULT_CAPACITY = 16;
/** Change this if the fields or inheritance hierarchy ever changes /** Change this if the fields or inheritance hierarchy ever changes (extremely unlikely). */
* (which is extremely unlikely). We override this because I'm tired
* of serialized crap not working depending on whether I compiled with
* jikes or javac. */
private static final long serialVersionUID = 1; private static final long serialVersionUID = 1;
} }