diff --git a/projects/samskivert/src/java/com/samskivert/util/ArrayIntSet.java b/projects/samskivert/src/java/com/samskivert/util/ArrayIntSet.java new file mode 100644 index 00000000..9010d6eb --- /dev/null +++ b/projects/samskivert/src/java/com/samskivert/util/ArrayIntSet.java @@ -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 true 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 java.util.Arrays 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; +} diff --git a/projects/samskivert/src/java/com/samskivert/util/IntSet.java b/projects/samskivert/src/java/com/samskivert/util/IntSet.java new file mode 100644 index 00000000..10edec39 --- /dev/null +++ b/projects/samskivert/src/java/com/samskivert/util/IntSet.java @@ -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 Integer + * objects. It extends the Set interface and therefore + * provides all of the standard methods (in which Integer + * objects will be converted to ints). + */ +public interface IntSet extends Set +{ + /** + * Returns true if this set contains the specified element. + * + * @param value element whose presence in this set is to be tested. + * + * @return true 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 + * false. 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 true if this set did not already contain the + * specified element. + * + * @throws UnsupportedOperationException if the add 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 true 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 remove 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 Collection.toArray method. + * + * @return an array containing all of the elements in this set. + */ + public int[] toIntArray (); +} diff --git a/projects/samskivert/tests/src/java/com/samskivert/util/ArrayIntSetTest.java b/projects/samskivert/tests/src/java/com/samskivert/util/ArrayIntSetTest.java new file mode 100644 index 00000000..30db2df8 --- /dev/null +++ b/projects/samskivert/tests/src/java/com/samskivert/util/ArrayIntSetTest.java @@ -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(); + } +}