I was getting type mismatch errors, until I refactored code to this:
public final Stream<Map.Entry<E, Integer>> orderedStreamOfEntries() {
return this.m_map.entrySet()
.stream()
.sorted(Comparator.comparingInt(Entry::getValue))
.map(AbstractMap.SimpleImmutableEntry::new);
}
- The return type is
Stream<Entry<E, Integer>> - The type of the stream at the end of this routine is
Stream<SimpleImmutableEntry<E, Integer>>
The formal type parameter E has this definition:
<E extends Enum<E> & MyCustomInterface>
I don't understand why this appears to be acceptable to the compiler. Because Java generics are invariant, even though java.util.AbstractMap.SimpleImmutableEntry implements java.util.Map.Entry, I would have said that Stream<SimpleImmutableEntry<>> is not a subtype of the return type, Stream<Entry<>>.
You're making two mistakes. The first is assuming
SimpleImmutableEntry::newis aFunction<Entry, SimpleImmutableEntry>*, when in fact it can be interpreted as aFunction<Entry, Entry>which happens to return aSimpleImmutableEntry.Secondly, look at the signature for
map():By returning
? extends R, the method is free to interpretRas a superclass of the lambdas return type, meaning even aFunction<Entry, SimpleImmutableEntry>could result in aStream<Entry>, or evenStream<Object>.The actual interpretation depends on the inferred return type, which in your case is
Stream<Entry>.*Raw entry types used for brevity.