IntSet/Interator cleanup.

- Fully filled-out AbstractIntSet with default implementations of most
  things and documented the two methods that must be provided (interator()
  and size()) as well as the ones that should probably be overridden for
  performance or to make one mutable.
- Fixed implementations of contains(Object o) and remove(Object o) to not NPE.
- Return hashCode() identically to the way Set<Integer> would.
- Created an AbstractInterator.
- Added notes where I believe an implementation is bogus...


git-svn-id: https://samskivert.googlecode.com/svn/trunk@2649 6335cc39-0255-0410-8fd6-9bcaacd3b74c
This commit is contained in:
ray.j.greenwell
2009-11-24 20:28:00 +00:00
parent dd4f8da52a
commit 5443630f99
6 changed files with 251 additions and 153 deletions
+162 -11
View File
@@ -21,34 +21,59 @@
package com.samskivert.util;
import java.util.AbstractSet;
import java.util.Collection;
import java.util.Iterator;
/**
* A base class for {@link IntSet} implementations.
* A base class for {@link IntSet} implementations.<p>
*
* All you really need to do is implement <tt>interable</tt> and <tt>size</tt>,
* although for performance reasons you'll probably want to override <tt>contains</tt>.<p>
*
* To implement a modifiable IntSet, the programmer must additionally override this class's
* <tt>add</tt> and <tt>remove</tt> methods, which will otherwise throw an
* <tt>UnsupportedOperationException</tt>.<p>
*/
public abstract class AbstractIntSet extends AbstractSet<Integer>
implements IntSet
{
@Override // from AbstractSet
public Iterator<Integer> iterator ()
/**
* {@inheritDoc}
*
* <p>This implementation iterates over the ints in the collection, checking each one in turn
* to see if it's the specified value.
*/
// from IntSet
public boolean contains (int value)
{
return interator();
// abstract implementation. You should override.
for (Interator it = interator(); it.hasNext(); ) {
if (it.nextInt() == value) {
return true;
}
}
return false;
}
// from IntSet
public boolean add (int t)
public boolean add (int value)
{
throw new UnsupportedOperationException();
}
// from IntSet
public boolean remove (int value)
{
throw new UnsupportedOperationException();
}
/**
* Creates an iterator that provides access to our int values without unboxing.
*/
public abstract Interator interator ();
/**
* Converts the contents of this set to an int array.
* {@inheritDoc}
*
* <p>This implementation returns an array containing all the elements returned by the
* interator.
*/
// from IntSet
public int[] toIntArray ()
{
int[] vals = new int[size()];
@@ -58,4 +83,130 @@ public abstract class AbstractIntSet extends AbstractSet<Integer>
}
return vals;
}
@Override // from AbstractSet<Integer>
public Iterator<Integer> iterator ()
{
return interator();
}
@Override // from AbstractSet<Integer>
public boolean contains (Object o)
{
return (o instanceof Integer) && contains(((Integer)o).intValue());
}
@Override // from AbstractSet<Integer>
public boolean add (Integer i)
{
if (i == null) {
throw new NullPointerException();
}
return add(i.intValue());
}
@Override // from AbstractSet<Integer>
public boolean remove (Object o)
{
return (o instanceof Integer) && remove(((Integer)o).intValue());
}
@Override // from AbstractSet<Integer>
public boolean equals (Object o)
{
if (o == this) {
return true;
}
if (o instanceof IntSet) {
IntSet that = (IntSet)o;
return (this.size() == that.size()) && this.containsAll(that);
}
return super.equals(o);
}
@Override // from AbstractSet<Integer>
public int hashCode ()
{
int h = 0;
for (Interator it = interator(); it.hasNext(); ) {
h += it.nextInt();
}
return h;
}
@Override // from AbstractSet<Integer>
public String toString ()
{
StringBuilder sb = new StringBuilder("[");
Interator it = interator();
if (it.hasNext()) {
sb.append(it.nextInt());
while (it.hasNext()) {
sb.append(", ").append(it.nextInt());
}
}
return sb.append(']').toString();
}
@Override // from AbstractSet<Integer>
public boolean containsAll (Collection<?> c)
{
if (c instanceof Interable) {
for (Interator it = ((Interable) c).interator(); it.hasNext(); ) {
if (!contains(it.nextInt())) {
return false;
}
}
return true;
}
return super.containsAll(c);
}
@Override // from AbstractSet<Integer>
public boolean addAll (Collection<? extends Integer> c)
{
if (c instanceof Interable) {
boolean modified = false;
for (Interator it = ((Interable) c).interator(); it.hasNext(); ) {
if (add(it.nextInt())) {
modified = true;
}
}
return modified;
}
return super.addAll(c);
}
@Override // from AbstractSet<Integer>
public boolean removeAll (Collection<?> c)
{
if (c instanceof Interable) {
boolean modified = false;
for (Interator it = ((Interable)c).interator(); it.hasNext(); ) {
if (remove(it.nextInt())) {
modified = true;
}
}
return modified;
}
return super.removeAll(c);
}
@Override // from AbstractSet<Integer>
public boolean retainAll (Collection<?> c)
{
if (c instanceof IntSet) {
IntSet that = (IntSet)c;
boolean modified = false;
for (Interator it = interator(); it.hasNext(); ) {
if (!that.contains(it.nextInt())) {
it.remove();
modified = true;
}
}
return modified;
}
return super.retainAll(c);
}
}
@@ -0,0 +1,39 @@
//
// $Id$
// samskivert library - useful routines for java programs
// Copyright (C) 2001-2009 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;
/**
* A building-block for writing an Interator.
*/
public abstract class AbstractInterator
implements Interator
{
// from super interface Iterator<Integer>
public Integer next ()
{
return Integer.valueOf(nextInt());
}
// from super interface Iterator<Integer>
public void remove ()
{
throw new UnsupportedOperationException();
}
}
+37 -108
View File
@@ -32,8 +32,8 @@ 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<Integer>
implements IntSet, Cloneable, Serializable
public class ArrayIntSet extends AbstractIntSet
implements Cloneable, Serializable
{
/**
* Construct an ArrayIntSet with the specified starting values.
@@ -124,6 +124,9 @@ public class ArrayIntSet extends AbstractSet<Integer>
*/
public int get (int index)
{
if (index >= _size) {
throw new IndexOutOfBoundsException("" + index + " >= " + _size);
}
return _values[index];
}
@@ -152,13 +155,13 @@ public class ArrayIntSet extends AbstractSet<Integer>
return values;
}
// from interface IntSet
@Override // from interface IntSet
public boolean contains (int value)
{
return (binarySearch(value) >= 0);
}
// from interface IntSet
@Override // from interface IntSet
public boolean add (int value)
{
int index = binarySearch(value);
@@ -190,7 +193,7 @@ public class ArrayIntSet extends AbstractSet<Integer>
return true;
}
// from interface IntSet
@Override // from interface IntSet
public boolean remove (int value)
{
int index = binarySearch(value);
@@ -216,23 +219,19 @@ public class ArrayIntSet extends AbstractSet<Integer>
// from interface IntSet
public Interator interator ()
{
return new Interator() {
return new AbstractInterator() {
public boolean hasNext () {
return (_pos < _size);
}
public int nextInt () {
if (_pos == _size) {
if (_pos >= _size) {
throw new NoSuchElementException();
} else {
return _values[_pos++];
}
}
public Integer next () {
return Integer.valueOf(nextInt());
}
public void remove () {
if (_pos == 0) {
throw new IllegalStateException();
@@ -248,16 +247,7 @@ public class ArrayIntSet extends AbstractSet<Integer>
};
}
// from interface IntSet
public Integer[] toArray (Integer[] a)
{
for (int i = 0; i < _size; i++) {
a[i] = Integer.valueOf(_values[i]);
}
return a;
}
// from interface IntSet
@Override // from interface IntSet
public int[] toIntArray ()
{
int[] values = new int[_size];
@@ -265,72 +255,31 @@ public class ArrayIntSet extends AbstractSet<Integer>
return values;
}
@Override // from AbstractSet<Integer>
public Object[] toArray ()
{
// TODO: this is wrong. We should be creating an Object[]
return toArray(new Integer[_size]);
}
// from AbstractSet<Integer>
public Integer[] toArray (Integer[] a)
{
// TODO: this is wrong. We need to be able to grow the array if necessary
// and null-terminate the values if the array is too large
for (int i = 0; i < _size; i++) {
a[i] = Integer.valueOf(_values[i]);
}
return a;
}
@Override // from AbstractSet<Integer>
public int size ()
{
return _size;
}
@Override // from AbstractSet<Integer>
public boolean isEmpty ()
{
return _size == 0;
}
@Override // from AbstractSet<Integer>
public boolean contains (Object o)
{
return contains(((Integer)o).intValue());
}
@Override // from AbstractSet<Integer>
public boolean add (Integer o)
{
return add(o.intValue());
}
@Override // from AbstractSet<Integer>
public boolean remove (Object o)
{
return remove(((Integer)o).intValue());
}
@Override // from AbstractSet<Integer>
public boolean containsAll (Collection<?> c)
{
if (c instanceof Interable) {
Interator inter = ((Interable) c).interator();
while (inter.hasNext()) {
if (!contains(inter.nextInt())) {
return false;
}
}
return true;
} else {
return super.containsAll(c);
}
}
@Override // from AbstractSet<Integer>
public boolean addAll (Collection<? extends Integer> c)
{
if (c instanceof Interable) {
Interator inter = ((Interable) c).interator();
boolean modified = false;
while (inter.hasNext()) {
if (add(inter.nextInt())) {
modified = true;
}
}
return modified;
} else {
return super.addAll(c);
}
}
@Override // from AbstractSet<Integer>
@Override // from AbstractIntSet
public boolean retainAll (Collection<?> c)
{
if (c instanceof IntSet) {
@@ -350,31 +299,17 @@ public class ArrayIntSet extends AbstractSet<Integer>
}
}
_size = _size - removals;
_size -= removals;
return (removals > 0);
} else {
return super.retainAll(c);
}
}
@Override // from AbstractSet<Integer>
public Iterator<Integer> iterator ()
{
return interator();
}
@Override // from AbstractSet<Integer>
public Object[] toArray ()
{
return toArray(new Integer[_size]);
return super.retainAll(c);
}
@Override // from AbstractSet<Integer>
public void clear ()
{
Arrays.fill(_values, 0);
_size = 0;
//Arrays.fill(_values, 0); // not necessary
}
@Override // from AbstractSet<Integer>
@@ -400,11 +335,11 @@ public class ArrayIntSet extends AbstractSet<Integer>
@Override // from AbstractSet<Integer>
public int hashCode ()
{
int hashCode = 0;
for (int i = 0; i < _size; i++) {
hashCode ^= _values[i];
int h = 0;
for (int ii = 0; ii < _size; ii++) {
h += _values[ii];
}
return hashCode;
return h;
}
@Override // from AbstractSet<Integer>
@@ -420,12 +355,6 @@ public class ArrayIntSet extends AbstractSet<Integer>
}
}
@Override // from AbstractSet<Integer>
public String toString ()
{
return StringUtil.toString(iterator());
}
/**
* 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
@@ -378,11 +378,11 @@ public class Collections
}
@Override
public boolean equals(Object o) {
public boolean equals(Object o) {
synchronized(mutex) {return c.equals(o);}
}
@Override
public int hashCode() {
public int hashCode() {
synchronized(mutex) {return c.hashCode();}
}
}
+9 -15
View File
@@ -397,13 +397,10 @@ public class HashIntMap<V> extends AbstractMap<Integer,V>
if (_keySet == null) {
_keySet = new AbstractIntSet() {
@Override public Interator interator () {
return new Interator () {
return new AbstractInterator () {
public boolean hasNext () {
return i.hasNext();
}
public Integer next () {
return i.next().getKey();
}
public int nextInt () {
return i.next().getIntKey();
}
@@ -418,20 +415,17 @@ public class HashIntMap<V> extends AbstractMap<Integer,V>
return HashIntMap.this.size();
}
@Override public boolean contains (Object t) {
@Override public boolean contains (int t) {
return HashIntMap.this.containsKey(t);
}
public boolean contains (int t) {
return HashIntMap.this.containsKey(t);
}
@Override public boolean remove (Object o) {
return (null != HashIntMap.this.remove(o));
}
public boolean remove (int value) {
return (null != HashIntMap.this.remove(value));
@Override public boolean remove (int value) {
// we need to be careful of null values
if (contains(value)) {
HashIntMap.this.remove(value);
return true;
}
return false;
}
};
}
+2 -17
View File
@@ -321,21 +321,10 @@ public class IntIntMap
return IntIntMap.this.size();
}
@Override public boolean contains (Object t) {
return (t instanceof Integer) ? IntIntMap.this.containsKey((Integer)t) : false;
}
public boolean contains (int t) {
return IntIntMap.this.containsKey(t);
}
@Override public boolean remove (Object o) {
if (!(o instanceof Integer)) {
return false;
}
return remove(((Integer)o).intValue());
}
public boolean remove (int value) {
// we have to check for presence in the map separately because we have no "not in
// the set" return value
@@ -561,9 +550,9 @@ public class IntIntMap
private int _modCount;
}
protected class KeyValueInterator implements Interator
protected class KeyValueInterator extends AbstractInterator
{
public KeyValueInterator (boolean keys, IntEntryIterator eiter) {
public KeyValueInterator (boolean keys, IntEntryIterator eiter) {
_keys = keys;
_eiter = eiter;
}
@@ -577,10 +566,6 @@ public class IntIntMap
return _eiter.hasNext();
}
public Integer next () {
return Integer.valueOf(nextInt());
}
public void remove () {
_eiter.remove();
}