diff --git a/src/java/com/samskivert/util/AbstractIntSet.java b/src/java/com/samskivert/util/AbstractIntSet.java index b425b098..14993ffa 100644 --- a/src/java/com/samskivert/util/AbstractIntSet.java +++ b/src/java/com/samskivert/util/AbstractIntSet.java @@ -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.

+ * + * All you really need to do is implement interable and size, + * although for performance reasons you'll probably want to override contains.

+ * + * To implement a modifiable IntSet, the programmer must additionally override this class's + * add and remove methods, which will otherwise throw an + * UnsupportedOperationException.

*/ public abstract class AbstractIntSet extends AbstractSet implements IntSet { - @Override // from AbstractSet - public Iterator iterator () + /** + * {@inheritDoc} + * + *

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} + * + *

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 } return vals; } + + @Override // from AbstractSet + public Iterator iterator () + { + return interator(); + } + + @Override // from AbstractSet + public boolean contains (Object o) + { + return (o instanceof Integer) && contains(((Integer)o).intValue()); + } + + @Override // from AbstractSet + public boolean add (Integer i) + { + if (i == null) { + throw new NullPointerException(); + } + return add(i.intValue()); + } + + @Override // from AbstractSet + public boolean remove (Object o) + { + return (o instanceof Integer) && remove(((Integer)o).intValue()); + } + + @Override // from AbstractSet + 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 + public int hashCode () + { + int h = 0; + for (Interator it = interator(); it.hasNext(); ) { + h += it.nextInt(); + } + return h; + } + + @Override // from AbstractSet + 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 + 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 + public boolean addAll (Collection 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 + 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 + 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); + } } diff --git a/src/java/com/samskivert/util/AbstractInterator.java b/src/java/com/samskivert/util/AbstractInterator.java new file mode 100644 index 00000000..6fcde827 --- /dev/null +++ b/src/java/com/samskivert/util/AbstractInterator.java @@ -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 + public Integer next () + { + return Integer.valueOf(nextInt()); + } + + // from super interface Iterator + public void remove () + { + throw new UnsupportedOperationException(); + } +} diff --git a/src/java/com/samskivert/util/ArrayIntSet.java b/src/java/com/samskivert/util/ArrayIntSet.java index a78a545c..5604bfb4 100644 --- a/src/java/com/samskivert/util/ArrayIntSet.java +++ b/src/java/com/samskivert/util/ArrayIntSet.java @@ -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 - 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 */ 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 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 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 // 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 }; } - // 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 return values; } + @Override // from AbstractSet + public Object[] toArray () + { + // TODO: this is wrong. We should be creating an Object[] + return toArray(new Integer[_size]); + } + + // from AbstractSet + 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 public int size () { return _size; } - @Override // from AbstractSet - public boolean isEmpty () - { - return _size == 0; - } - - @Override // from AbstractSet - public boolean contains (Object o) - { - return contains(((Integer)o).intValue()); - } - - @Override // from AbstractSet - public boolean add (Integer o) - { - return add(o.intValue()); - } - - @Override // from AbstractSet - public boolean remove (Object o) - { - return remove(((Integer)o).intValue()); - } - - @Override // from AbstractSet - 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 - public boolean addAll (Collection 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 + @Override // from AbstractIntSet public boolean retainAll (Collection c) { if (c instanceof IntSet) { @@ -350,31 +299,17 @@ public class ArrayIntSet extends AbstractSet } } - _size = _size - removals; + _size -= removals; return (removals > 0); - - } else { - return super.retainAll(c); } - } - - @Override // from AbstractSet - public Iterator iterator () - { - return interator(); - } - - @Override // from AbstractSet - public Object[] toArray () - { - return toArray(new Integer[_size]); + return super.retainAll(c); } @Override // from AbstractSet public void clear () { - Arrays.fill(_values, 0); _size = 0; + //Arrays.fill(_values, 0); // not necessary } @Override // from AbstractSet @@ -400,11 +335,11 @@ public class ArrayIntSet extends AbstractSet @Override // from AbstractSet 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 @@ -420,12 +355,6 @@ public class ArrayIntSet extends AbstractSet } } - @Override // from AbstractSet - public String toString () - { - return StringUtil.toString(iterator()); - } - /** * 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 diff --git a/src/java/com/samskivert/util/Collections.java b/src/java/com/samskivert/util/Collections.java index a2455a4f..ad600434 100644 --- a/src/java/com/samskivert/util/Collections.java +++ b/src/java/com/samskivert/util/Collections.java @@ -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();} } } diff --git a/src/java/com/samskivert/util/HashIntMap.java b/src/java/com/samskivert/util/HashIntMap.java index 4e0d11d7..168b6276 100644 --- a/src/java/com/samskivert/util/HashIntMap.java +++ b/src/java/com/samskivert/util/HashIntMap.java @@ -397,13 +397,10 @@ public class HashIntMap extends AbstractMap 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 extends AbstractMap 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; } }; } diff --git a/src/java/com/samskivert/util/IntIntMap.java b/src/java/com/samskivert/util/IntIntMap.java index 3e490724..def3b76b 100644 --- a/src/java/com/samskivert/util/IntIntMap.java +++ b/src/java/com/samskivert/util/IntIntMap.java @@ -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(); }