19

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

当迭代这样的条目集时,为什么这不能编译?

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()) {
        ...
    }
}
4

6 回答 6

24

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

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().

于 2013-02-18T10:19:29.157 回答
7

这是因为您使用原始类型 Map,因此 map.entrySet() 为您提供了一个非参数化的 Set,它在迭代时生成 Object,而不是 Entry。

一个简单但优雅的解决方案是使用 Map<?,?>,它仍然允许您传递 ANY Map,但另一方面强制 map.entrySet() 具有 Set<Entry> 的返回值:

public void test(Map<?,?> map) {        
    for(Entry e : map.entrySet()){
        Object key = e.getKey();
        Object value = e.getValue();
    }       
}
于 2013-02-18T10:40:49.430 回答
2

在第一个示例中,map.entrySet() 返回 Set,当您在循环中迭代时使用 Iterator。没有关于设置内容类型的信息,因此 Java 使用 Object 作为 Object 是基本类型,编译器告诉您它不能将 Object 转换为 Entry。

Set<Map.Entry<K, V>> entrySet();

当您使用原始地图类型时,entrySet 只返回 Set,没有类型信息。

在第二个示例中,您手动将 Set 转换为 Set<Entry> (带有警告)。现在 Java 知道里面有什么了。所以你可以迭代。

在上一个示例中,您知道映射类型,因此 entrySet 返回正确的类型化 Set 并且您可以在没有任何类型约定的情况下进行迭代。

于 2013-02-18T10:20:05.097 回答
1

第一个代码片段不会编译,因为该变量map不存在。您调用了该参数anyMap,但尝试将其访问map

于 2013-02-18T10:06:16.967 回答
0

我遇到了同样的问题。看来选角是个问题。我尝试了下面的代码并且它有效。

    for(Object entry : hashMap.entrySet())
    {
        System.out.println(((Entry<Object, Object>) entry).getKey() + " = " + ((Entry<Object, Object>) entry).getValue());

    }
于 2017-10-04T09:21:39.483 回答
0

您收到编译时错误,因为您没有指定类型HashMap

HashMap <(Integer,String> hm=new HashMap<(Integer,String>();  

如果将类型指定为 Integer 和 String,则不会出现编译时错误。

如果您不知道要在 HashMap 中添加哪个值,那么您使用

HashMap<(Object,Object> hm=new HashMap();  
于 2017-11-10T06:58:57.083 回答