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)
Run Code Online (Sandbox Code Playgroud)
我发现奇怪的是,通配符已用于确保前两个参数尽可能通用,但第三个参数只是一个BinaryOperator<U>.如果它们一致,那肯定会是一个BiFunction<? super U,? super U,? extends U>?我错过了什么吗?有没有充分的理由,或者他们只是想避免使已经可怕的签名更糟糕?
编辑
我理解PECS,并且我理解mergeFunction应该被认为是一种获取两个U并且取回一个的方法的原则U.然而,能够拥有可以以许多不同方式重用的对象将是有用的.例如:
static final BiFunction<Number, Number, Double>
MULTIPLY_DOUBLES = (a, b) -> a.doubleValue() * b.doubleValue();
Run Code Online (Sandbox Code Playgroud)
显然这不是一个BinaryOperator<Double>,但它可以被视为一个.这将是巨大的,如果你能使用MULTIPLY_DOUBLES的都一BiFunction<Number, Number, Double>和BinaryOperator<Double>,根据上下文.特别是,您可以简单地传递MULTIPLY_DOUBLES以指示您希望double使用乘法减少s 的负载.但是toMap(Java 8中的其他新方法)的签名不允许这种灵活性.
你是对的,合并操作的功能签名(同样适用于reduce)不需要像BinaryOperator.
这不仅可以通过收集器mergeFunction的 的toMap最终Map.merge接受 a 的事实来说明BiFunction<? super V,? super V,? extends V>;您还可以将这样的 a 转换BiFunction为所需的BinaryOperator:
BiFunction<Number, Number, Double> \n MULTIPLY_DOUBLES = (a, b) -> a.doubleValue() * b.doubleValue();\nStream<Double> s = Stream.of(42.0, 0.815);\nOptional<Double> n=s.reduce(MULTIPLY_DOUBLES::apply);\nRun Code Online (Sandbox Code Playgroud)\n\n或完整通用:
\n\npublic static <T> Optional<T> reduce(\n Stream<T> s, BiFunction<? super T, ? super T, ? extends T> f) {\n return s.reduce(f::apply);\n}\nRun Code Online (Sandbox Code Playgroud)\n\nBinaryOperator创建和的最可能的原因UnaryOperator是与这些函数的原始类型版本具有对称性,这些函数没有\xe2\x80\x99t 具有这样的超级接口。
在这方面,方法是一致的
\n\nStream.reduce(BinaryOperator<T>)IntStream.reduce(IntBinaryOperator)DoubleStream.reduce(DoubleBinaryOperator)LongStream.reduce(LongBinaryOperator)或者
\n\nArrays.parallelPrefix(T[] array, BinaryOperator<T> op)Arrays.parallelPrefix(int[] array, IntBinaryOperator op)Arrays.parallelPrefix(double[] array, DoubleBinaryOperator op)Arrays.parallelPrefix(long[] array, LongBinaryOperator op)