Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to replace wildcard generic when customizing Collectors.toMap

I have a Collector function that is basically toMap but always a LinkedHashMap as I need this often. Sonar complains about the ? wildcard generic in the return type. Seeing as this is the exact same signature as the toMap method, and I'm at it's mercy, how would I replace the wildcard with a proper value or generic?

I've tried Map<K,U> and adding an M extends Map<K,U> and LinkedHashMap versions of those as well, but nothing compiles.

Any suggestions?

Or is this impossible as I am using Collectors.toMap which uses a wildcard?

public static <T, K, U> Collector<T, ?, LinkedHashMap<K, U>> toLinkedHashMap(
        Function<? super T, ? extends K> keyMapper,
        Function<? super T, ? extends U> valueMapper,
        BinaryOperator<U> merger) {
    return Collectors.toMap(keyMapper, valueMapper, merger, LinkedHashMap::new);
}

Here is the full text of the Sonar rule:

Generic wildcard types should not be used in return parameters

Code smell

Major

squid:S1452

Using a wildcard as a return type implicitly means that the return value should be considered read-only, but without any way to enforce this contract. Let's take the example of method returning a List<? extends Animal>. Is it possible on this list to add a Dog, a Cat, ... we simply don't know. The consumer of a method should not have to deal with such disruptive questions.

Non-compliant Code Example

List<? extends Animal> getAnimals(){...}

like image 225
Novaterata Avatar asked Jun 14 '17 18:06

Novaterata


1 Answers

It is impossible as long as you use Collections.toMap().

You could copy-and-paste that function (and the mapMerger() function on which it depends), declaring the return type as Collector<T, LinkedHashMap<K,U>, LinkedHashMap<K,U>>. But I think it would be better to keep your code clean and deal with Sonar. Perhaps there's a way to indicate that this is a false positive, and suppress warnings from Sonar.

like image 146
erickson Avatar answered Nov 13 '22 01:11

erickson