Here's my complete wrapper. It's rather simplistic and could probably use
some optimization in .equals, but I didn't try an awful lot.
Comments welcome.
/**
* A wrapper of HashMap that support recursion in values (can contain itself
as a value) and still calculate
* hashCode and equals correctly.
*/
public class FixedHashMap<K,V> extends HashMap<K,V> {
protected boolean _inHashCode = false;
protected HashSet<FixedHashMap<?,?>> _inEqualsWith = new
HashSet<FixedHashMap<?,?>>();
@Override
public int hashCode() {
int result = 0;
if (_inHashCode ) { return result; }
_inHashCode = true;
result = super.hashCode();
_inHashCode = false;
return result;
}
/**
* Equals needs to fix the case of comparing two recursive maps. The
rest is handled by the default implementation.
*/
@Override
public boolean equals(Object other) {
if (this == other) {
return true;
}
if (null == other) {
return false;
}
if (!(other instanceof HashMap)) {
return false;
}
if (!(other instanceof FixedHashMap)) {
// We assume other is a non-recursive map,
// and the default .equals doesn't recurse infinitely
return super.equals(other);
}
// It may be a recursive map.
FixedHashMap<?, ?> savedOther = (FixedHashMap<?, ?>) other;
if (this._inEqualsWith.contains(savedOther)) {
// We are already comparing ourselves with this object!
// Return 'true' because the final result will be the
conjunction ('and')
// of this result and all the other entries. If all the other
entries are equal,
// we can say the maps are equal.
return true;
}
this._inEqualsWith.add(savedOther);
boolean res = super.equals(other);
this._inEqualsWith.remove(savedOther);
return res;
}
}
--
http://groups.google.com/group/Google-Web-Toolkit-Contributors