Various cleanuppery: added containsKey(), deprecated contains(), added

getOrElse() and removeOrElse() and encourage their use in the class
documentation (I was tempted to deprecate get() and remove() but I think that's
going too far).


git-svn-id: https://samskivert.googlecode.com/svn/trunk@2550 6335cc39-0255-0410-8fd6-9bcaacd3b74c
This commit is contained in:
samskivert
2009-05-04 00:26:44 +00:00
parent 5b1328e768
commit 2247e7d0a0
+117 -90
View File
@@ -26,23 +26,22 @@ import java.io.ObjectOutputStream;
import java.io.Serializable; import java.io.Serializable;
import java.util.AbstractSet; import java.util.AbstractSet;
import java.util.Iterator;
import java.util.ConcurrentModificationException; import java.util.ConcurrentModificationException;
import java.util.Iterator;
import java.util.NoSuchElementException; import java.util.NoSuchElementException;
import java.util.Set; import java.util.Set;
/** /**
* An int int map is like an int map, but with integers as values as well * An int int map is like an int map, but with integers as values as well as keys. Be careful:
* as keys. Note that in situations where null would normally be returned * {@link #get} and {@link #remove} return -1 to indicate that no previous mapping existed. Use
* to indicate no value, -1 is returned instead. This means that you must * {@link #getOrElse} and {@link #removeOrElse} to use a different "default" value.
* be careful if you intend to store -1 as a valid value in the table.
*/ */
//
// TODO: make this a proper map, perhaps even an extension of HashIntMap
// or at least share a common abstract ancestor.
public class IntIntMap public class IntIntMap
implements Serializable implements Serializable
{ {
// TODO: make this a proper map, perhaps even an extension of HashIntMap or at least share a
// common abstract ancestor.
public interface IntIntEntry extends IntMap.IntEntry<Integer> public interface IntIntEntry extends IntMap.IntEntry<Integer>
{ {
public int getIntValue (); public int getIntValue ();
@@ -78,11 +77,17 @@ public class IntIntMap
return _size == 0; return _size == 0;
} }
/**
* Returns the number of mappings.
*/
public int size () public int size ()
{ {
return _size; return _size;
} }
/**
* Adds the supplied key/value mapping. Any previous mapping for that key will be overwritten.
*/
public void put (int key, int value) public void put (int key, int value)
{ {
_modCount++; _modCount++;
@@ -115,10 +120,22 @@ public class IntIntMap
_size++; // we're bigger _size++; // we're bigger
} }
/**
* Returns the value mapped to the specified key or -1 if there is no mapping.
*/
public int get (int key) public int get (int key)
{
return getOrElse(key, -1);
}
/**
* Returns the value mapped to the specified key or the supplied default value if there is no
* mapping.
*/
public int getOrElse (int key, int defval)
{ {
Record rec = locateRecord(key); Record rec = locateRecord(key);
return (rec == null) ? -1 : rec.value; return (rec == null) ? defval : rec.value;
} }
/** /**
@@ -139,11 +156,78 @@ public class IntIntMap
} }
} }
/**
* Returns true if this map contains a mapping for the specified key.
*
* @Deprecated use {@link #containsKey}.
*/
public boolean contains (int key) public boolean contains (int key)
{ {
return (null != locateRecord(key)); return (null != locateRecord(key));
} }
/**
* Returns true if this map contains a mapping for the specified key.
*/
public boolean containsKey (int key)
{
return (null != locateRecord(key));
}
/**
* Removes the value mapped for the specified key.
*
* @return the value to which the key was mapped or -1 if there was no mapping for that key.
*/
public int remove (int key)
{
return removeOrElse(key, -1);
}
/**
* Removes the value mapped for the specified key.
*
* @return the value to which the key was mapped or the supplied default value if there was no
* mapping for that key.
*/
public int removeOrElse (int key, int defval)
{
_modCount++;
int removed = removeImpl(key, defval);
checkShrink();
return removed;
}
/**
* Clears all mappings.
*/
public void clear ()
{
_modCount++;
// abandon all of our hash chains (the joy of garbage collection)
for (int i = 0; i < _buckets.length; i++) {
_buckets[i] = null;
}
// zero out our size
_size = 0;
}
/**
* Ensure that the hash can comfortably hold the specified number of elements. Calling this
* method is not necessary, but can improve performance if done prior to adding many elements.
*/
public void ensureCapacity (int minCapacity)
{
int size = _buckets.length;
while (minCapacity > (int) (size * _loadFactor)) {
size *= 2;
}
if (size != _buckets.length) {
resizeBuckets(size);
}
}
/** /**
* Internal method to locate the record for the specified key. * Internal method to locate the record for the specified key.
*/ */
@@ -158,15 +242,10 @@ public class IntIntMap
return null; return null;
} }
public int remove (int key) /**
{ * Internal method for removing a mapping.
_modCount++; */
int removed = removeImpl(key); protected int removeImpl (int key, int defval)
checkShrink();
return removed;
}
protected int removeImpl (int key)
{ {
int index = Math.abs(key)%_buckets.length; int index = Math.abs(key)%_buckets.length;
Record prev = null; Record prev = null;
@@ -185,35 +264,7 @@ public class IntIntMap
prev = rec; prev = rec;
} }
return -1; // not found return defval; // not found
}
public void clear ()
{
_modCount++;
// abandon all of our hash chains (the joy of garbage collection)
for (int i = 0; i < _buckets.length; i++) {
_buckets[i] = null;
}
// zero out our size
_size = 0;
}
/**
* Ensure that the hash can comfortably hold the specified number
* of elements. Calling this method is not necessary, but can improve
* performance if done prior to adding many elements.
*/
public void ensureCapacity (int minCapacity)
{
int size = _buckets.length;
while (minCapacity > (int) (size * _loadFactor)) {
size *= 2;
}
if (size != _buckets.length) {
resizeBuckets(size);
}
} }
/** /**
@@ -419,102 +470,80 @@ public class IntIntMap
class IntEntryIterator implements Iterator<IntIntEntry> class IntEntryIterator implements Iterator<IntIntEntry>
{ {
public IntEntryIterator () public IntEntryIterator () {
{
this._modCount = IntIntMap.this._modCount; this._modCount = IntIntMap.this._modCount;
_index = _buckets.length; _index = _buckets.length;
} }
/** public boolean hasNext () {
* Check for concurrent modifications.
*/
protected void checkMods ()
{
if (this._modCount != IntIntMap.this._modCount) {
throw new ConcurrentModificationException("IntIntMapIterator");
}
}
public boolean hasNext ()
{
checkMods(); checkMods();
// if we're pointing to an entry, we've got more entries // if we're pointing to an entry, we've got more entries
if (_next != null) { if (_next != null) {
return true; return true;
} }
// search backward through the buckets looking for the next non-empty hash chain
// search backward through the buckets looking for the next
// non-empty hash chain
while (_index-- > 0) { while (_index-- > 0) {
if ((_next = _buckets[_index]) != null) { if ((_next = _buckets[_index]) != null) {
return true; return true;
} }
} }
// found no non-empty hash chains, we're done // found no non-empty hash chains, we're done
return false; return false;
} }
public IntIntEntry next () public IntIntEntry next () {
{ // if we're not pointing to an entry, search for the next non-empty hash chain
// if we're not pointing to an entry, search for the next
// non-empty hash chain
if (hasNext()) { if (hasNext()) {
_prev = _next; _prev = _next;
_next = _next.next; _next = _next.next;
return _prev; return _prev;
} else { } else {
throw new NoSuchElementException("IntIntMapIterator"); throw new NoSuchElementException("IntIntMapIterator");
} }
} }
public void remove () public void remove () {
{
checkMods(); checkMods();
if (_prev == null) { if (_prev == null) {
throw new IllegalStateException("IntIntMapIterator"); throw new IllegalStateException("IntIntMapIterator");
} }
// otherwise remove the hard way // otherwise remove the hard way
removeImpl(_prev.key); removeImpl(_prev.key, -1);
_prev = null; _prev = null;
} }
protected void checkMods () {
if (this._modCount != IntIntMap.this._modCount) {
throw new ConcurrentModificationException("IntIntMapIterator");
}
}
private int _index; private int _index;
private Record _next, _prev; private Record _next, _prev;
private int _modCount; private int _modCount;
} }
protected class KeyValueInterator protected class KeyValueInterator implements Interator
implements Interator
{ {
public KeyValueInterator (boolean keys, IntEntryIterator eiter) public KeyValueInterator (boolean keys, IntEntryIterator eiter) {
{
_keys = keys; _keys = keys;
_eiter = eiter; _eiter = eiter;
} }
public int nextInt () public int nextInt () {
{
IntIntEntry entry = _eiter.next(); IntIntEntry entry = _eiter.next();
return _keys ? entry.getIntKey() : entry.getIntValue(); return _keys ? entry.getIntKey() : entry.getIntValue();
} }
public boolean hasNext () public boolean hasNext () {
{
return _eiter.hasNext(); return _eiter.hasNext();
} }
public Integer next () public Integer next () {
{
return Integer.valueOf(nextInt()); return Integer.valueOf(nextInt());
} }
public void remove () public void remove () {
{
_eiter.remove(); _eiter.remove();
} }
@@ -548,9 +577,7 @@ public class IntIntMap
private Record[] _buckets; private Record[] _buckets;
private int _size; private int _size;
protected float _loadFactor; protected float _loadFactor;
protected int _modCount = 0; protected int _modCount = 0;
/** Change this if the fields or inheritance hierarchy ever changes. */ /** Change this if the fields or inheritance hierarchy ever changes. */