Here's the best I've been able to do so far at avoiding code duplication:
private abstract class AbstractChildSet<T extends Map.Entry<K,V>> extends AbstractSet<T> {
@Override
public boolean remove(Object o) {
if (o == null || !(o instanceof Map.Entry)) {
return false;
}
MapTreeNode<K,V> node;
if (o instanceof MapTreeNode)
node = (MapTreeNode<K,V>) o;
else
node = MapTreeNode.this.child(((Map.Entry<K,V>) o).getKey());
if (node == null || !isParentOf(node))
return false;
node.removeFromParent();
return true;
}
@Override
public int size() {
return MapTreeNode.this.childCount();
}
@Override
public void clear() {
MapTreeNode.this.removeAllChildren();
}
}
private final class ChildSet extends AbstractChildSet<MapTreeNode<K,V>> {
@Override
public boolean add(MapTreeNode<K,V> node) {
if (MapTreeNode.this.containsKey(node.getKey()))
return false;
MapTreeNode.this.addChild(node);
return true;
}
@Override
public Iterator<MapTreeNode<K,V>> iterator() {
return children.values().iterator();
}
}
private final class EntrySet extends AbstractChildSet<Map.Entry<K,V>> {
@Override
public boolean add(Map.Entry<K,V> entry) {
if (MapTreeNode.this.containsKey(entry.getKey()))
return false;
MapTreeNode new_child = new HashMapTreeNode(MapTreeNode.this, entry.getKey(), entry.getValue());
MapTreeNode.this.addChild(new_child);
return true;
}
@Override
public Iterator<Map.Entry<K,V>> iterator() {
return new EntryIterator();
}
}