2017-10-28 109 views
1

我实现了一个基于两个类型参数<K,V>的地图,其中K是关键类型,而V是值类型。为什么这些类型不是分配兼容的,我如何定义一个赋值兼容类?

public class Map<K,V> implements Map<K,V> 
{ .. implementation .. } 

Map接口中的一种方法返回一组映射条目。

public Set<java.util.Map.Entry<K,V>> entrySet() 

由于我的地图的实现是基于AVL树,另一个类必须实现为Set<MapNode>

public class EntrySet<K,V> implements Set<MapNode<K,V>> 
{ .. implementation ..} 

为了告诉大家,地图树的节点的确映射条目,它们是定义如下:

public class MapNode<K,V> implements Map.Entry<K,V> 
{ .. implementation .. } 

的entrySet所以包含相同的树作为Map本身,而是把该树节点作为元素集合(其这就是为什么它必须单独实施)。

在地图上实现的方法,返回一套条目,因此应如下所示:

/* (non-Javadoc) 
* @see java.util.Map#entrySet() 
*/ 
@Override 
public Set<java.util.Map.Entry<K,V>> entrySet() 
{ 
    return new EntrySet<K,V>(this.comparator,this.tree); 
} 

然而,编译器给了我以下错误:

“类型不匹配:不能转换从EntrySet<K,V>Set<Map.Entry<K,V>>

我的问题:

  • 我的以下假设是否正确? (或者,如果没有,是什么问题?)

一套Map.Entry<K,V>必须能够包含的Map.Entry<K,V>所有排序,不只是MapNode<K,V>对象。因此,在逻辑上不是EntrySet<K,V> a Set<Map.Entry<K,V>,并且因此这两种集合类型不被认为是分配兼容的。

  • 是否有任何其他的方式来定义一个类EntrySet<K,V>,基于相同的树结构(我做希望通过创建或调用其他的数据结构,以增加运行时间),使得这个类的一个对象可以无论何处需要Set<Map.Entry<K,V>

更新:

我曾尝试以下版本:

public class EntrySet<K,V> implements Set<MapNode<K,V>> 
{ .. implementation ..} 

在这种情况下,迭代器创建一个类似的问题。存在即整齐地遍历整棵树的迭代器类,但它被定义为一个超类的MapNode<K,V>的迭代,而这个迭代器不能转换为所需Iterator<Map.Entry<K,V>>

@Override 
public Iterator<Map.Entry<K,V>> iterator() 
{ 
    // this iterator type can not be cast to the desired return type 
    return new TreeNodeIterator<MapNode<K,V>,K>(this.tree); 
} 

我可能复制整个迭代器代码并粗暴地使用它在一个新的,独立的迭代类,但我更喜欢更优雅的解决方案。

所以我仍然卡在这里。

更新:

在平均时间,我已经创造了另一个独立的迭代器类,盒原来迭代器,并相应地转换“下一个”元素。这并不是很优雅,但至少它现在可行。不过,任何更优雅的解决方案都将非常受欢迎!

回答

1

Why are these types not assignment compatible?

的问题是,Map::entrySet()签名说,它应该返回一组任何Map.Entry<K,V>对象。但是您返回的对象仅支持对象为MapNode的条目。

的(概念)的原因,这是一个问题,是一个Set允许插入以及取出元件,并且所述Set<java.util.Map.Entry<K,V>>::add(...)应该能够任何Map.Entry<K,V>添加到该集合。但是您的EntrySet实施的签名不会允许这样做。

我建议你试试这个:

public class EntrySet<K,V> implements Set<? extends Map.Entry<K,V>> 
    { .. implementation ..} 

或本

public class EntrySet<K,V> implements Set<Map.Entry<K,V>> 
    { .. implementation ..} 
+0

感谢我的假设的确认。至于解决方案的想法 - 我只是试了一下,编译器告诉我“超类型可能没有指定任何通配符”。 – BlondMammuth

+0

试试另一个。 –