I have a class Foo
which overrides equals()
and hashCode()
properly.
I would like to also would like to use a HashSet<Foo>
to keep track of "canonical values" e.g. I have a class that I would like to write like this, so that if I have two separate objects that are equivalent I can coalesce them into references to the same object:
class Canonicalizer<T>
{
final private Set<T> values = new HashSet<T>();
public T findCanonicalValue(T value)
{
T canonical = this.values.get(value);
if (canonical == null)
{
// not in the set, so put it there for the future
this.values.add(value);
return value;
}
else
{
return canonical;
}
}
}
except that Set
doesn't have a "get" method that would return the actual value stored in the set, just the "contains" method that returns true or false. (I guess that it assumes that if you have an object that is equal to a separate object in the set, you don't need to retrieve the one in the set)
Is there a convenient way to do this? The only other thing I can think of is to use a map and a list:
class Canonicalizer<T>
{
// warning: neglects concurrency issues
final private Map<T, Integer> valueIndex = new HashMap<T, Integer>();
final private List<T> values = new ArrayList<T>();
public T findCanonicalValue(T value)
{
Integer i = this.valueIndex.get(value);
if (i == null)
{
// not in the set, so put it there for the future
i = this.values.size();
this.values.add(value);
this.valueIndex.put(value, i);
return value;
}
else
{
// in the set
return this.values.get(i);
}
}
}