我正在尝试扩展AbstractMap以创建一个MapTreeNode类(一个树节点,通过键而不是通过索引访问子项)。

我已经有一种方法可以让一组孩子正常工作:

public class MapTreeNode<K,V> implements Map.Entry<K,V> {
    private Map<K,MapTreeNode<K,V>> children = new HashMap<K,MapTreeNode<K,V>>();
    private Set<MapTreeNode<K,V>> child_set = null;

    public Set<MapTreeNode<K,V>> children() {
        if (child_set == null)
            child_set = new ChildSet();

        return child_set;
    }

    ...

    private final class ChildSet extends AbstractSet<MapTreeNode<K,V>> {
        @Override
        public Iterator<MapTreeNode<K,V>> iterator() {
            return children.values().iterator();
        }

        @Override
        public int size() {
            return MapTreeNode.this.childCount();
        }
        ...
    }

}


我想创建一个节点(Map<K,V>)的地图视图并重用child_set,但是我不确定Java的泛型是否可行:

public Map<K,V> asMap() {
    return new AbstractMap<K,V>() {
        @Override
        public Set<Map.Entry<K,V>> entrySet() {
            return child_set; // line 166
        }
    };
}


这当然给

MapTreeNode:166: incompatible types
found   : java.util.Set<MapTreeNode<K,V>>
required: java.util.Set<java.util.MapEntry<K,V>>


有什么方法可以重用我的ChildSet类吗?

最佳答案

问题出在entrySet()的返回类型上。是Set<Map.Entry<K,V>>。如您所知,对于不同的A和B,Foo<A>Foo<B>不兼容,无论它们如何关联。

我认为这是API中的设计错误。 entrySet()的返回类型实际上应该是Set<? extends Map.Entry<K,V>>。这是为什么:如果您阅读entrySet()documentation,它表示可以从Set中读取内容,可以从Set中删除内容(这会导致基础地图发生更改),但是无法将内容添加到集合。这恰好适合生产者的角色-您无需在其中添加任何内容。根据PECS规则,应使用extends通配符收集类型。

10-04 10:18