Iterating over a map entryset

39,070

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

Solution 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();
    }       
}

Solution 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.

Solution 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

Share:
39,070
Sergio
Author by

Sergio

Updated on July 05, 2022

Comments

  • Sergio
    Sergio almost 2 years

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