迭代地图输入集

时间:2013-02-18 10:02:09

标签: java loops generics map entryset

我需要遍历地图的入口集,我不知道它的参数化类型。

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

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

6 个答案:

答案 0 :(得分:23)

你在第一个错误中得到的错误是:

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>。< / p>

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

答案 1 :(得分:6)

这是因为你使用原始类型Map,因此map.entrySet()会获得一个非参数化的Set,它反过来在迭代时产生Object,而不是Entry。

一个简单但优雅的解决方案是使用Map&lt;?,?&gt;,它仍然允许您传递任何Map,但另一方面强制map.entrySet()返回值Set&lt; Entry&gt ;:

public void test(Map<?,?> map) {        
    for(Entry e : map.entrySet()){
        Object key = e.getKey();
        Object value = e.getValue();
    }       
}

答案 2 :(得分:2)

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

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

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

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

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

答案 3 :(得分:1)

第一个代码段不会编译,因为变量map不存在。您调用了参数anyMap,但尝试将其作为map访问,修复了该问题,您的代码将从一些rawtypes警告中进行编译

答案 4 :(得分:0)

由于您没有在HashMap

中指定类型,因此您正在获取编译时间错误

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

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

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

HashMap<(Object,Object> hm=new HashMap();  

答案 5 :(得分:-1)

我遇到了同样的问题。似乎铸造是一个问题。我尝试了下面的代码并且有效。

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

    }