java - 为什么这些类型不兼容赋值,如何定义赋值兼容的类?

标签 java generics interface

我基于两个类型参数实现了一个映射 <K,V> ,其中K是 key 类型且 V是值类型。

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

Map 中的一种方法接口(interface)返回映射条目集。

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

由于我的 map 实现基于 AVL 树,因此必须将另一个类实现为 Set<MapNode>

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

为了表明 map 树的节点确实是 map 条目,它们的定义如下:

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

因此 EntrySet 包含与 Map 相同的树本身,但将树节点视为集合元素(这就是它必须单独实现的原因)。

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> 的情况并非如此。 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>的父类(super class)的迭代器。 ,并且此迭代器无法转换为所需的 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);
}

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

所以我还被困在这里。

更新:

同时,我创建了另一个独立的迭代器类,它将原始迭代器装箱并相应地转换“下一个”元素。这并不是很优雅,但至少暂时有效。尽管如此,任何更优雅的解决方案都将受到欢迎!

最佳答案

Why are these types not assignment compatible?

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

这是一个问题的(概念)原因是 Set允许插入和删除元素,并且 Set<java.util.Map.Entry<K,V>>::add(...) 应该能够添加任何 Map.Entry<K,V>到集合。但你的 EntrySet 的签名不允许这样做。实现。

How can I define an assignment compatible class?

我建议你尝试一下:

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 ..}

关于java - 为什么这些类型不兼容赋值,如何定义赋值兼容的类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46988576/

相关文章:

java - 在数组中正确使用协方差

java - Matlab 无法读取 JAR 资源

swift - 为什么是 'there cannot be more than one conformance, even with different conditional bounds' ?

c# - CS0246 : The type or namespace name `T' could not be found. 是否缺少 using 指令或程序集引用?在 C# 中

java - 使用 JAXB 编码空值

java - 如何使用模式匹配获取子字符串

arrays - Array 中的 Swift 泛型子类行为

iphone - .h文件名与@interface名称iOS不匹配时会发生什么

java - 我如何实例化?包含代码

C#接口(interface)方法歧义