Eu já precisei de algo parecido e fiz algo como sugeriu o louds. Criei uma classe que implementava Map<MeuTipoQueQueroAgrupar, Integer> e usava um campo do tipo TreeMap para fazer forward. Aí, no método put da minha classe, se uma chave já existente fosse inserida, eu incrementava o Integer associado a ela. Análogo para remove.
[size=18]NOTA DE EDIÇÃO[/size]
Olha ela aqui:
package br.com.autbank.bcel.data.collection;
import br.com.autbank.bcel.data.ClassMemberUsageDescriptor;
import br.com.autbank.tech.util.iteration.Maps;
import java.util.Collection;
import java.util.Comparator;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.TreeSet;
public class ClassMemberUsageMap
implements
SortedMap<ClassMemberUsageDescriptor, Long>,
Cloneable
{
private TreeMap<ClassMemberUsageDescriptor, Long> treeMap;
public ClassMemberUsageMap() {
treeMap = new TreeMap<ClassMemberUsageDescriptor, Long>();
}
public ClassMemberUsageMap(Comparator<? super ClassMemberUsageDescriptor> comparator) {
treeMap = new TreeMap<ClassMemberUsageDescriptor, Long>(comparator);
}
public ClassMemberUsageMap(ClassMemberUsageMap cmuMap) {
treeMap = new TreeMap<ClassMemberUsageDescriptor, Long>(cmuMap);
}
public ClassMemberUsageMap(Collection<ClassMemberUsageDescriptor> cmuds) {
treeMap = new TreeMap<ClassMemberUsageDescriptor, Long>();
putAll(cmuds);
}
public ClassMemberUsageMap(Map<? extends ClassMemberUsageDescriptor, ? extends Long> map) {
this.treeMap = new TreeMap<ClassMemberUsageDescriptor, Long>(map);
}
public ClassMemberUsageMap(SortedMap<ClassMemberUsageDescriptor, ? extends Long> sortedMap) {
treeMap = new TreeMap<ClassMemberUsageDescriptor, Long>(sortedMap);
}
public String desc() {
return Maps.toString(treeMap, " = ", "\n");
}
public Set<Entry<ClassMemberUsageDescriptor, Long>> cut(long by, boolean inclusive){
Set<Entry<ClassMemberUsageDescriptor, Long>> result =
new TreeSet<Entry<ClassMemberUsageDescriptor,Long>>();
Iterator<Entry<ClassMemberUsageDescriptor, Long>> entries =
treeMap.entrySet().iterator();
while(entries.hasNext()) {
Entry<ClassMemberUsageDescriptor, Long> entry =
entries.next();
boolean mustCut = inclusive ?
entry.getValue() <= by :
entry.getValue() < by
;
if(mustCut) {
result.add(entry);
entries.remove();
}
}
return result;
}
public void clear() {
treeMap.clear();
}
public boolean containsKey(Object key) {
return treeMap.containsKey(key);
}
public boolean containsValue(Object value) {
return treeMap.containsValue(value);
}
public Set<Entry<ClassMemberUsageDescriptor, Long>> entrySet() {
return treeMap.entrySet();
}
public Long get(Object key) {
return treeMap.get(key);
}
public boolean isEmpty() {
return treeMap.isEmpty();
}
public Set<ClassMemberUsageDescriptor> keySet() {
return treeMap.keySet();
}
public Long put(ClassMemberUsageDescriptor key) {
return put(key, 1L);
}
public Long put(ClassMemberUsageDescriptor key, Long value) {
if(treeMap.containsKey(key))
return treeMap.put(key, Long.valueOf(treeMap.get(key) + value));
else
return treeMap.put(key, Long.valueOf(1));
}
public void putAll(Map<? extends ClassMemberUsageDescriptor, ? extends Long> map) {
putAll(new ClassMemberUsageMap(map));
}
public void putAll(ClassMemberUsageMap cmuMap) {
for(Entry<ClassMemberUsageDescriptor, Long> entry: cmuMap.entrySet()) {
ClassMemberUsageDescriptor key = entry.getKey();
Long value = entry.getValue();
if(treeMap.containsKey(key))
treeMap.put(key, treeMap.get(key) + value);
else
treeMap.put(key, value);
}
}
public void putAll(Collection<? extends ClassMemberUsageDescriptor> descriptors) {
for (ClassMemberUsageDescriptor cmud : descriptors) {
put(cmud);
}
}
public Long remove(Object key) {
if(treeMap.containsKey(key)) {
Long value = get(key);
if(value > 1)
return treeMap.put(
(ClassMemberUsageDescriptor)key,
Long.valueOf(treeMap.get(key) - 1)
);
}
return treeMap.remove(key);
}
public int size() {
return treeMap.size();
}
public Collection<Long> values() {
return treeMap.values();
}
public Comparator<? super ClassMemberUsageDescriptor> comparator() {
return treeMap.comparator();
}
public ClassMemberUsageDescriptor firstKey() {
return treeMap.firstKey();
}
public SortedMap<ClassMemberUsageDescriptor, Long> headMap(ClassMemberUsageDescriptor toKey) {
return treeMap.headMap(toKey);
}
public ClassMemberUsageDescriptor lastKey() {
return treeMap.lastKey();
}
public SortedMap<ClassMemberUsageDescriptor, Long> subMap(ClassMemberUsageDescriptor fromKey, ClassMemberUsageDescriptor toKey) {
return treeMap.subMap(fromKey, toKey);
}
public SortedMap<ClassMemberUsageDescriptor, Long> tailMap(ClassMemberUsageDescriptor fromKey) {
return treeMap.tailMap(fromKey);
}
@SuppressWarnings("unchecked")
protected Object clone(){
ClassMemberUsageMap cloned = new ClassMemberUsageMap();
cloned.treeMap =
(TreeMap<ClassMemberUsageDescriptor, Long>) this.treeMap.clone();
return cloned;
}
public String toString() {
return Maps.toString(treeMap, "\t", "\n");
}
}