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