简体   繁体   中英

Incompatible generic type for result returned by Java iterator

I have an object which is a type of Map, and I am trying to iterate it with iterator. However, I cannot pass the compile, the code are as following.

// Returned from other method, and the run time type is Map<String, B>
Map<String, ? extends A> map = ...

// Option 1: cannot pass.
Iterator<Map.Entry<String, ? extends A>> iterator = map.entrySet().iterator();

// Option 2: cannot pass either.
// Where B is a subclass extends from A
Iterator<Map.Entry<String, B>> iterator = map.entrySet().iterator();

Can someone help me out? Thanks.

I suggest you use the foreach loop instead of using the Iterator directly

Map<String, ? extends A> map = new HashMap<>();
for (Map.Entry<String, ? extends A> entry : map.entrySet()) {
    String key = entry.getKey();
    A value = entry.getValue();
}

If you really want to store the Iterator in a variable, instead of this

// ERROR
Iterator<Map.Entry<String, ? extends A>> iterator = map.entrySet().iterator();

you have to do this:

Iterator<? extends Map.Entry<String, ? extends A>> iterator = map.entrySet().iterator();

The reason for the extra ? extends ? extends is the wildcard nested in in the Map.Entry<String, ? extends A> Map.Entry<String, ? extends A> declaration. If you had a variable of type

Iterator<Map.Entry<String, ? extends A>>

then in principle each entry could have a value of a different subtype of A, so each Map.Entry would be of a different type. By contrast,

Iterator<? extends Map.Entry<String, ? extends A>>

means that each entry is of a single type. (But you don't know what type it is, since it's a wildcard.)

In practice, this doesn't matter for Iterator since you're only getting objects of type Map.Entry<String, ? extends A> Map.Entry<String, ? extends A> out of it. But if you had some other type that allowed you to put things into it (such as a Set ) then the difference would be significant. For example,

Set<? extends Map.Entry<String, ? extends A>>

would only allow getting entries from the set, but

Set<Map.Entry<String, ? extends A>>

would allow adding entries to the set, and those entries might contain different subtypes of A, possibly polluting the set.

For further discussion on this, see

as well as these Stack Overflow questions:

I this this should do the trick

for (Map.Entry<String, ? extends A> entry : map.entrySet())
{
   String key = entry.getKey();
    A value = entry.getValue();
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM