Iterating over a map entryset

戏子无情 提交于 2019-11-27 23:19:43

问题


I need to iterate over the entry set of a map from which I do not know its parameterized types.

When iterating over such entryset, why this does not compile ?

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

but this compile:

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

and this also compiles (I cannot use this one since I do not know the types of the map):

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

回答1:


The error you get in your first one is:

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

This is because the compiler converts your FOR-IN loop:

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

To:

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

Your second example works, but only through cheating! You are doing an unchecked cast to get Set back into a Set<Entry>.

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

Becomes:

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

Update

As mentioned in comments, the type information is getting lost in both examples: because of the compiler's raw type erasure rules.

To provide backwards compatibility, ALL methods of raw type instances are replaced by their erased counterparts. So, because your Map is a raw type, it all gets erased. Including its Set<Map.Entry<K, V>> entrySet(); method: your raw type instance will be forced to use the erased version: Set entrySet().




回答2:


It is because you use the raw type Map, therefore map.entrySet() gets you a non-parametrized Set which in return yields Object on iteration, not Entry.

A simple, but elegant solution is to use Map<?,?>, which will still allow you to pass ANY Map, but on the other hand forces map.entrySet() to have a return value of Set<Entry>:

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



回答3:


In first example, map.entrySet() returns Set, when you iterate in loop you use Iterator. There is no information about set content type, so Java use Object as Object is base type and compiler tells you that it can't convert Object to Entry.

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

When you use raw map type, entrySet returns just Set, with no type information.

In second example, you manualy convert Set to Set<Entry> (with warning). Now Java knows what inside it. So you can iterate.

In last example you know map type, so entrySet returns correct typed Set and you can iterate without any type conventions.




回答4:


the first code snippet wont compile because the variable map does not exist. You called the parameter anyMap but tried to access it as map, fix that and your code will compile aside from some rawtypes warnings




回答5:


I have faced the same problem. It seems that the casting is a problem. I tried the below code and it worked.

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

    }



回答6:


You're getting the compile time rrror because you are not specifying the type in HashMap

Like

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

If you specify the type as Integer and String, you don't get the compile time error.

IF you Dont Know which Value is going to Add in your HashMap then You Use

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


来源:https://stackoverflow.com/questions/14933648/iterating-over-a-map-entryset

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!