Java 8 предоставила нам новые методы с очень длинными сигнатурами, такими как:
static <T,K,U,M extends Map<K,U>> Collector<T,?,M> toMap(
Function<? super T,? extends K> keyMapper,
Function<? super T,? extends U> valueMapper,
BinaryOperator<U> mergeFunction, Supplier<M> mapSupplier)
То, что я считаю странным, заключается в том, что для обеспечения того, чтобы первые два параметра были как можно более общими, были использованы подстановочные знаки, но третий параметр - это просто BinaryOperator<U>
. Если бы они были согласованы, то это было бы BiFunction<? super U,? super U,? extends U>
?. Я что-то упускаю? Есть ли веская причина для этого, или они просто хотят избежать еще более ужасной подписи?
Edit
Я понимаю PECS, и я понимаю принцип, что mergeFunction
следует рассматривать как способ взять два U
и вернуть a U
. Однако было бы полезно иметь объект, который можно было бы повторно использовать разными способами. Например:
static final BiFunction<Number, Number, Double>
MULTIPLY_DOUBLES = (a, b) -> a.doubleValue() * b.doubleValue();
Очевидно, что это не BinaryOperator<Double>
, но его можно рассматривать как единое целое. Было бы здорово, если бы вы использовали MULTIPLY_DOUBLES
как a BiFunction<Number, Number, Double>
, так и BinaryOperator<Double>
, в зависимости от контекста. В частности, вы можете просто передать MULTIPLY_DOUBLES
, чтобы указать, что вы хотите уменьшить нагрузку double
с помощью умножения. Однако подпись для toMap
(и других новых методов в Java 8) не допускает такой гибкости.