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);
}
Stream<Entry<E, Integer>>
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::new
is a Function<Entry, SimpleImmutableEntry>
*, when in fact it can be interpreted as a Function<Entry, Entry>
which happens to return a SimpleImmutableEntry
.
Secondly, look at the signature for map()
:
<R> Stream<R> map(Function<? super T, ? extends R> mapper)
By returning ? extends R
, the method is free to interpret R
as a superclass of the lambdas return type, meaning even a Function<Entry, SimpleImmutableEntry>
could result in a Stream<Entry>
, or even Stream<Object>
.
The actual interpretation depends on the inferred return type, which in your case is Stream<Entry>
.
*Raw entry types used for brevity.