3

我有一个对象模型,它有一个父对象,我将在这里调用它 MyParent.java。该类有两个名为 MySub1.java 和 MySub2.java 的子类。

我有两个 HashMap,一个包含 MySub1 实例,另一个包含 MySub2 实例。我正在尝试编写一段代码,它可以同时处理 HashMap 并执行完全相同的操作(稍后,拥有 MySub1 或 MySub2 实例会产生一些影响,但不是在这里)。

这是编译的代码部分:

HashMap<String, ? extends MyParent> map = null;
if (some condition)
    map = // get a HashMap<String, MySub1>
if (some other condition)
    map = // get a HashMap<String, MySub2>

但是现在,我无法弄清楚如何迭代map变量。我需要通过迭代器而不是通过对元素的迭代来完成它,keySet()因为我需要从哈希图中删除一些元素。

这是我的代码中未编译的部分:

if(map != null && map.size() > 0){
    Iterator<Entry<String, ? extends MyParent>> i = map.entrySet().iterator();
    while(i.hasNext()){
        Map.Entry<String, MyParent> pair = (Map.Entry<String, MyParent>) i.next();
        // get the object from the pair and handle it
    }
}

Eclipse 确实在我创建迭代器的行上打印了这条错误消息:

 cannot convert from Iterator<Map.Entry<String,capture#5-of ? extends MyParent>> to Iterator<Map.Entry<String,? extends MyParent>>

我真的没有收到错误信息。如果我将代码的第一行更改为:

HashMap<String, MyParent> map = null

现在,不工作的代码确实可以工作,但是工作代码不再工作,并出现以下错误消息:

cannot convert from HashMap<String,MySub1> to HashMap<String,MyParent>

任何的想法 ?

4

2 回答 2

3

您始终可以将 String 和 MyParent 的一对实例放入Map<String,MyParent>. 您不能将该对放入Map<String,MySub1>. 因此,无法从后者转换为前一个地图(如您最后一条错误消息所述)。另请参阅关于协变和逆变的维基百科

相同问题的一个版本适用于迭代器。如果您的实际地图是 a Map<String,MySub1>,它会返回一个,即使 a是 a Iterator<Map.Entry<String,MySub1>>,它也不能转换为 a 。例如,以下将编译:Iterator<Map.Entry<String,? extends MyParent>>Map.Entry<String,MySub1>Map.Entry<String,? extends MyParent>

Map.Entry<String,? extends MyParent> someEntry = map.entrySet().iterator().next();.

另一个通配符 ( ?) 在这里有帮助:

Iterator<? extends Map.Entry<String, ? extends MyParent>> i =  map.entrySet().iterator();
于 2013-02-21T08:04:43.023 回答
0

我不知道您的确切要求,但在同一张地图中有多个对象类型可能会产生严重的维护问题。希望你会考虑以下场景

  1. 当两个条件在稍后的某个时间点都满足时

  2. 当 Mysub1/Mysub2 的行为发生变化时。

  3. 当其他人在维护代码时。

    我仍然建议使用单独的实例。为了避免到处携带多个地图,您可能希望将它们包裹在一个对象中。

于 2013-02-21T08:24:21.657 回答