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