遍历地图条目集


问题内容

我需要遍历不知道其参数化类型的映射的条目集。

遍历此类入口集时,为什么不编译呢?

public void myMethod(Map anyMap) {
    for(Entry entry : anyMap.entrySet()) {
        ...
    }
}

但这编译:

public void myMethod(Map anyMap) {
    Set<Entry> entries = anyMap.entrySet();
    for(Entry entry : entries) {
        ...
    }
}

并且也可以编译(由于我不知道地图的类型,所以我不能使用它):

public void myMethod(Map<String, String> stringMap) {
    for(Entry<String,String> entry : stringMap.entrySet()) {
        ...
    }
}

问题答案:

您在第一个错误中遇到的错误是:

Type mismatch: cannot convert from element type Object to Map.Entry

这是因为编译器会转换FOR-IN循环:

for (Entry entry : anyMap.entrySet()) {
}

至:

for (Iterator i = anyMap.entrySet().iterator(); i.hasNext();) {
    Entry e = i.next(); // not allowed
}

您的第二个示例有效, 但只能通过作弊! 您正在进行未经检查的演员表转换,以Set 恢复Set<Entry>

Set<Entry> entries = anyMap.entrySet(); // you get a compiler warning here
for (Entry entry : entries) {
}

成为:

Set<Entry> entries = anyMap.entrySet();
for (Iterator<Entry> i = entries.iterator(); i.hasNext(); ) {
    Entry e = (Entry) i.next(); // allowed
}

更新资料

如注释中所述,在两个示例中,类型信息都将丢失:由于编译器的原始类型擦除规则。

为了提供向后兼容性,原始类型实例的 所有 方法都将由其 擦除的
对应对象代替。因此,由于您Map是原始类型,因此将其全部删除。包括其Set<Map.Entry<K, V>> entrySet();方法:您的原始类型实例将被迫使用已删除的版本:Set entrySet()