Could anybody explain, why next code isn’t compiling?
I’m creating a partially-specialized Map and Map.Entry for it:
public class Trie<T> implements Map<String, T> {
private class TrieEntry<S> implements Map.Entry<String, S> {
// stupid implementation here
}
// uninterested code here
}
Here everything is ok, but then i’m implementing entrySet() method:
public Set<java.util.Map.Entry<String, T>> entrySet() {
Set<java.util.Map.Entry<String, T>> x = new HashSet<TrieEntry<T>>();
// some uninterested code here
}
Eclipse says
“Type mismatch: cannot convert from HashSet<Trie<T>.TrieEntry<T>> to Set<Map.Entry<String,T>>“
So, in my mind TrieEntry<T> should be unrolled to Map.Entry<String, T> and it accords to expression in definition.
Where am I wrong?
You are right that a
TrieEntry<T>is aMap.Entry<String, T>. AHashSet<TrieEntry<T>>is also aSet<TrieEntry<T>>, but it is not aSet<Map.Entry<String, T>>.If it were you could do this:
So now trieSet would now contain a
Map.Entry<String, T>! This would break generics.So how to solve this particular problem? Easy – use a bounded wildcard:
You can read
? extends Map.Entry<String, T>as "anything which is at least aMap.Entry<String, T>".Okay, now to your implementation problem. I actually believe, that this is not solveable in this way because of the current definition of the method entrySet(). It should return
? extends Map.Entry<String, T>, but it does returnMap.Entry<String, T>.There is actually a bug report (or feature request) for exactly this problem. Looking at the submit date and the priority, a fix can’t be expected soon.
So you have two options:
Drop your
TrieEntryclass and try to useMap.Entryinstead, storing information in your keys and/or values.Drop the
Mapinterface and let your customentrySetmethod return? extends Map.Entry<String, T>.Both solutions may not be ideal, and there may be better solutions, but this is all what I currently can tell you.