Implemented an efficient integer set class that uses a sorted array of

integers to maintain its contents.


git-svn-id: https://samskivert.googlecode.com/svn/trunk@559 6335cc39-0255-0410-8fd6-9bcaacd3b74c
This commit is contained in:
mdb
2002-02-03 07:10:16 +00:00
parent 1b26bab85b
commit 3af18399cd
3 changed files with 416 additions and 0 deletions
@@ -0,0 +1,274 @@
//
// $Id: ArrayIntSet.java,v 1.1 2002/02/03 07:10:16 mdb Exp $
//
// samskivert library - useful routines for java programs
// Copyright (C) 2001 Michael Bayne
//
// 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
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
package com.samskivert.util;
import java.util.AbstractSet;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.NoSuchElementException;
/**
* Provides an {@link IntSet} implementation using a sorted array of
* integers to maintain the contents of the set.
*/
public class ArrayIntSet extends AbstractSet
implements IntSet
{
// documentation inherited from interface
public int size ()
{
return _size;
}
// documentation inherited from interface
public boolean isEmpty ()
{
return _size == 0;
}
// documentation inherited from interface
public boolean contains (Object o)
{
return contains(((Integer)o).intValue());
}
// documentation inherited from interface
public boolean contains (int value)
{
return (binarySearch(value) >= 0);
}
// documentation inherited from interface
public Iterator iterator ()
{
return new Iterator() {
public boolean hasNext () {
return (_pos < _size);
}
public Object next () {
if (_pos == _size) {
throw new NoSuchElementException();
} else {
return new Integer(_values[_pos++]);
}
}
public void remove () {
throw new UnsupportedOperationException();
}
protected int _pos;
};
}
// documentation inherited from interface
public Object[] toArray ()
{
return toArray(new Integer[_size]);
}
// documentation inherited from interface
public Object[] toArray (Object[] a)
{
for (int i = 0; i < _size; i++) {
a[i] = new Integer(_values[i]);
}
return a;
}
// documentation inherited from interface
public int[] toIntArray ()
{
int[] values = new int[_size];
System.arraycopy(_values, 0, values, 0, _size);
return values;
}
// documentation inherited from interface
public boolean add (Object o)
{
return add(((Integer)o).intValue());
}
// documentation inherited from interface
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[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;
}
// documentation inherited from interface
public boolean remove (Object o)
{
return remove(((Integer)o).intValue());
}
// documentation inherited from interface
public boolean remove (int value)
{
int index = binarySearch(value);
if (index > 0) {
System.arraycopy(_values, index, _values, index+1, --_size-index);
_values[_size] = 0;
return true;
}
return false;
}
// documentation inherited from interface
public boolean containsAll (Collection c)
{
Iterator iter = c.iterator();
while (iter.hasNext()) {
if (!contains(iter.next())) {
return false;
}
}
return true;
}
// documentation inherited from interface
public boolean addAll (Collection c)
{
boolean modified = false;
Iterator iter = c.iterator();
while (iter.hasNext()) {
modified = (add(iter.next()) || modified);
}
return modified;
}
// documentation inherited from interface
public boolean retainAll (Collection c)
{
throw new UnsupportedOperationException();
}
// documentation inherited from interface
public void clear ()
{
Arrays.fill(_values, 0);
_size = 0;
}
// documentation inherited from interface
public boolean equals (Object o)
{
if (o instanceof ArrayIntSet) {
ArrayIntSet other = (ArrayIntSet)o;
if (other._size == _size) {
return Arrays.equals(_values, other._values);
}
}
return false;
}
// documentation inherited from interface
public int hashCode ()
{
int hashCode = 0;
for (int i = 0; i < _size; i++) {
hashCode ^= _values[i];
}
return hashCode;
}
/**
* Performs a binary search on our values array, looking for the
* specified value. Swiped from <code>java.util.Arrays</code> because
* those wankers didn't provide a means by which to perform a binary
* search on a subset of an array.
*/
protected int binarySearch (int key)
{
int low = 0;
int high = _size-1;
while (low <= high) {
int mid = (low + high) >> 1;
int midVal = _values[mid];
if (midVal < key) {
low = mid + 1;
} else if (midVal > key) {
high = mid - 1;
} else {
return mid; // key found
}
}
return -(low + 1); // key not found.
}
/** An array containing the values in this set. */
protected int[] _values = new int[16];
/** The number of elements in this set. */
protected int _size;
}
@@ -0,0 +1,84 @@
//
// $Id: IntSet.java,v 1.1 2002/02/03 07:10:16 mdb Exp $
//
// samskivert library - useful routines for java programs
// Copyright (C) 2001 Michael Bayne
//
// 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
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
package com.samskivert.util;
import java.util.Set;
/**
* A set that holds integers and provides accessors that eliminate the
* need to create and manipulate superfluous <code>Integer</code>
* objects. It extends the <code>Set</code> interface and therefore
* provides all of the standard methods (in which <code>Integer</code>
* objects will be converted to ints).
*/
public interface IntSet extends Set
{
/**
* Returns <tt>true</tt> if this set contains the specified element.
*
* @param value element whose presence in this set is to be tested.
*
* @return <tt>true</tt> if this set contains the specified element.
*/
public boolean contains (int value);
/**
* Adds the specified element to this set if it is not already present
* (optional operation). If this set already contains the specified
* element, the call leaves this set unchanged and returns
* <tt>false</tt>. In combination with the restriction on
* constructors, this ensures that sets never contain duplicate
* elements.
*
* @param value element to be added to this set.
*
* @return <tt>true</tt> if this set did not already contain the
* specified element.
*
* @throws UnsupportedOperationException if the <tt>add</tt> method is
* not supported by this set.
*/
public boolean add (int value);
/**
* Removes the specified element from this set if it is present
* (optional operation). Returns <tt>true</tt> if the set contained
* the specified element (or equivalently, if the set changed as a
* result of the call). (The set will not contain the specified
* element once the call returns.)
*
* @param value element to be removed from this set, if present.
*
* @return true if the set contained the specified element.
*
* @throws UnsupportedOperationException if the <tt>remove</tt> method
* is not supported by this set.
*/
public boolean remove (int value);
/**
* Returns an array containing all of the elements in this set. Obeys
* the general contract of the <tt>Collection.toArray</tt> method.
*
* @return an array containing all of the elements in this set.
*/
public int[] toIntArray ();
}
@@ -0,0 +1,58 @@
//
// $Id: ArrayIntSetTest.java,v 1.1 2002/02/03 07:10:16 mdb Exp $
//
// samskivert library - useful routines for java programs
// Copyright (C) 2001 Michael Bayne
//
// 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
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
package com.samskivert.util;
import java.util.Arrays;
import junit.framework.Test;
import junit.framework.TestCase;
import com.samskivert.Log;
public class ArrayIntSetTest extends TestCase
{
public ArrayIntSetTest ()
{
super(ArrayIntSetTest.class.getName());
}
public void runTest ()
{
ArrayIntSet set = new ArrayIntSet();
set.add(3);
set.add(5);
set.add(5);
set.add(9);
set.add(5);
set.add(7);
set.add(1);
int[] values = { 1, 3, 5, 7, 9 };
int[] setvals = set.toIntArray();
assert("values equal", Arrays.equals(values, setvals));
}
public static Test suite ()
{
return new ArrayIntSetTest();
}
}