I use this lambda expression to find a nested object
Optional<? extends OnlineResource> onlineResourceOptional =
metadata.getDistributionInfo().stream()
.filter(Objects::nonNull)
.flatMap(distribution -> distribution.getTransferOptions().stream())
.filter(Objects::nonNull)
.flatMap(digitalTransferOptions -> digitalTransferOptions.getOnLines().stream())
.filter(Objects::nonNull)
.filter(onlineResource -> onlineResource.getProtocol().equals("OGC:STA"))
.findFirst()
;
It returns a generic Optional<? extends OnlineResource> because of the flatmap method but I want it to return a Optional<OnlineResource>. How can I achieve that?
It seems that either or both methods,
getTransferOptions()and/orgetOnLines()return a collection with a wildcard type, likeCollection<? extends …>. This is strongly discouraged:Which means precisely the problem you ran into. You should preferably fix these methods rather than the caller. If this is not possible, you may workaround the issue by specifying an explicit type for the
flatMapoperation instead of relying on type inference.E.g., if you have code like
change it to
to
flatMapto aStream<Number>, rather thanStream<? extends Number>. This works, because theflatMaphas been declared asallowing the specified function to return a stream of subtypes. This is an application of the PECS rule.
But as said, it’s preferable to fix the collection returning methods. More than often, they also call methods following the PECS rule and hence, allow changing an element type from
? extends EtoE.It might be helpful to know the following features:
If you already have an immutable collection like those created with
List.of(…), you can use methodsList.copyOf(…)orSet.copyOf(…)to widen their element type without a copy.This works, because the immutability prevent callers from adding an
Objectto thisList<String>. Likewise, you can create an unmodifiable view to any collection to avoid dealing with wildcard types:This creates a new
Listinstance, but without copying the contents, so it’s still cheap. But, as said, more than often, there are already methods involved which allow changing the type to the desired wildcard free type by just inserting the explicit type at an earlier point.