Got a wild hair and added some methods to CountHashMap, and added
an Entry interface that can be used to get the count directly from an Entry (without having to know that values are stored internally as an int[]). It turned out to be a bit ugly. What I really need to do is hide all the int[] business by rewriting this class, which will also clean up the ugliness. git-svn-id: https://samskivert.googlecode.com/svn/trunk@1839 6335cc39-0255-0410-8fd6-9bcaacd3b74c
This commit is contained in:
@@ -18,17 +18,34 @@
|
||||
|
||||
package com.samskivert.util;
|
||||
|
||||
import java.util.AbstractSet;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* A hashmap that maintains a count for each key.
|
||||
*
|
||||
* This implementation may change, but I find it useful to inherit all
|
||||
* the goodness of clear(), keySet(), size(), etc.
|
||||
* This implementation should change so that we extend AbstractMap, do our
|
||||
* own hashing, and can use our own Entry class.
|
||||
*/
|
||||
public class CountHashMap<K> extends HashMap<K,int[]>
|
||||
public class CountHashMap<K> extends HashMap<K, int[]>
|
||||
{
|
||||
public interface Entry<K> extends Map.Entry<K, int[]>
|
||||
{
|
||||
/**
|
||||
* Get the value of the entry as an int.
|
||||
*/
|
||||
public int getCount ();
|
||||
|
||||
/**
|
||||
* Set the value of this entry as an int.
|
||||
* @return the old count
|
||||
*/
|
||||
public int setCount (int count);
|
||||
}
|
||||
|
||||
/**
|
||||
* Increment the value associated with the specified key, return
|
||||
* the new value.
|
||||
@@ -41,6 +58,20 @@ public class CountHashMap<K> extends HashMap<K,int[]>
|
||||
}
|
||||
val[0] += amount;
|
||||
return val[0];
|
||||
|
||||
/* Alternate implementation, less hashing on the first increment
|
||||
* but more garbage created every other time.
|
||||
* (this whole method would be more optimal if this class were
|
||||
* rewritten)
|
||||
*
|
||||
int[] newVal = new int[] { amount };
|
||||
int[] oldVal = put(key, newVal);
|
||||
if (oldVal != null) {
|
||||
newVal[0] += oldVal[0];
|
||||
return oldVal[0];
|
||||
}
|
||||
return 0;
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -52,6 +83,23 @@ public class CountHashMap<K> extends HashMap<K,int[]>
|
||||
return (val == null) ? 0 : val[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the count for the specified key.
|
||||
*
|
||||
* @return the old count.
|
||||
*/
|
||||
public int setCount (K key, int count)
|
||||
{
|
||||
int[] val = get(key);
|
||||
if (val == null) {
|
||||
put(key, new int[] { count });
|
||||
return 0; // old value
|
||||
}
|
||||
int oldVal = val[0];
|
||||
val[0] = count;
|
||||
return oldVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the total count for all keys in the map.
|
||||
*/
|
||||
@@ -63,4 +111,125 @@ public class CountHashMap<K> extends HashMap<K,int[]>
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compress the count map- remove entries for which the value is 0.
|
||||
*/
|
||||
public void compress ()
|
||||
{
|
||||
for (Iterator<int[]> itr = values().iterator(); itr.hasNext(); ) {
|
||||
if (itr.next()[0] == 0) {
|
||||
itr.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public Set<Map.Entry<K, int[]>> entrySet ()
|
||||
{
|
||||
// a giant mess of hoop-jumpery so that we can convert each Map.Entry
|
||||
// returned by the iterator to be a CountEntryImpl
|
||||
return new CountEntrySet(super.entrySet());
|
||||
}
|
||||
|
||||
protected static class CountEntryImpl<K>
|
||||
implements Entry<K>
|
||||
{
|
||||
public CountEntryImpl (Map.Entry<K, int[]> entry)
|
||||
{
|
||||
_entry = entry;
|
||||
}
|
||||
|
||||
public boolean equals (Object o)
|
||||
{
|
||||
return _entry.equals(o);
|
||||
}
|
||||
|
||||
public K getKey ()
|
||||
{
|
||||
return _entry.getKey();
|
||||
}
|
||||
|
||||
public int[] getValue ()
|
||||
{
|
||||
return _entry.getValue();
|
||||
}
|
||||
|
||||
public int hashCode ()
|
||||
{
|
||||
return _entry.hashCode();
|
||||
}
|
||||
|
||||
public int[] setValue (int[] value)
|
||||
{
|
||||
return _entry.setValue(value);
|
||||
}
|
||||
|
||||
public int getCount ()
|
||||
{
|
||||
return getValue()[0];
|
||||
}
|
||||
|
||||
public int setCount (int count)
|
||||
{
|
||||
int[] val = getValue();
|
||||
int oldVal = val[0];
|
||||
val[0] = count;
|
||||
return oldVal;
|
||||
}
|
||||
|
||||
protected Map.Entry<K, int[]> _entry;
|
||||
}
|
||||
|
||||
protected class CountEntrySet<K>
|
||||
extends AbstractSet<Entry<K>>
|
||||
{
|
||||
public CountEntrySet (Set superset)
|
||||
{
|
||||
_superset = superset;
|
||||
}
|
||||
|
||||
public Iterator<Entry<K>> iterator ()
|
||||
{
|
||||
final Iterator<Map.Entry<K, int[]>> itr = _superset.iterator();
|
||||
return new Iterator<Entry<K>>() {
|
||||
public boolean hasNext ()
|
||||
{
|
||||
return itr.hasNext();
|
||||
}
|
||||
|
||||
public Entry<K> next ()
|
||||
{
|
||||
return new CountEntryImpl(itr.next());
|
||||
}
|
||||
|
||||
public void remove ()
|
||||
{
|
||||
itr.remove();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public boolean contains (Object o)
|
||||
{
|
||||
return _superset.contains(o);
|
||||
}
|
||||
|
||||
public boolean remove (Object o)
|
||||
{
|
||||
return _superset.remove(o);
|
||||
}
|
||||
|
||||
public int size ()
|
||||
{
|
||||
return CountHashMap.this.size();
|
||||
}
|
||||
|
||||
public void clear ()
|
||||
{
|
||||
CountHashMap.this.clear();
|
||||
}
|
||||
|
||||
protected Set _superset;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user