From 5443630f99b77307bf698a830c1e99b26859eead Mon Sep 17 00:00:00 2001 From: "ray.j.greenwell" Date: Tue, 24 Nov 2009 20:28:00 +0000 Subject: [PATCH] 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 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 --- .../com/samskivert/util/AbstractIntSet.java | 173 ++++++++++++++++-- .../samskivert/util/AbstractInterator.java | 39 ++++ src/java/com/samskivert/util/ArrayIntSet.java | 145 ++++----------- src/java/com/samskivert/util/Collections.java | 4 +- src/java/com/samskivert/util/HashIntMap.java | 24 +-- src/java/com/samskivert/util/IntIntMap.java | 19 +- 6 files changed, 251 insertions(+), 153 deletions(-) create mode 100644 src/java/com/samskivert/util/AbstractInterator.java 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(); }