0xb*_*00d 8 java generics functor java-8
请考虑以下两个功能:
public static <X, Y, U, V extends X> Function<U, Y> composite(
Function<X, Y> first, Function<U, V> second)
{
Objects.requireNonNull(first);
Objects.requireNonNull(second);
return (U arg) -> first.apply(second.apply(arg));
}
public static <X, Y extends X> Function<X, ?> iterate(Function<X, Y> function, int n)
{
if (n < 0)
return null;
if (n == 0)
return (X arg) -> arg;
Objects.requireNonNull(function);
Function<X, Y> iteration = function;
for (; n > 1; --n)
iteration = composite(function, iteration);
return iteration;
}
Run Code Online (Sandbox Code Playgroud)
而composite(first, second)计算组合物的first和second,iterate(function, n)计算nth 迭代的function.
虽然限制Y extends X足以满足任何要求n > 0,但我们遇到了一些问题n == 0.在数学上,iterate应该产生身份功能.但是,我们也需要X extends Y,也就是说X == Y.
请考虑以下示例
Function<Double, Double> nthSquareRoot = iterate(Math::sqrt, n);
Run Code Online (Sandbox Code Playgroud)
这会产生错误消息:
Type mismatch: cannot convert from Function<Double,capture#2-of ?> to Function<Double,Double>
Run Code Online (Sandbox Code Playgroud)
这里最好的选择是什么?如果n == 1,我们可以检查是否X可以接受Y.我想听听其他选项和一些想法如何执行此检查(据我所知,没有简单的解决方案来检查两个通用参数是否相等).
尝试:
public static<X> UnaryOperator<X> iterate(UnaryOperator<X> f, int n) { ... }
Run Code Online (Sandbox Code Playgroud)
如果Y <:X,那么从X到Y的函数也是从X到X的函数,你应该能够做你想要的.
您需要更改结果的类型以考虑通配符:
Function<Double, ? extends Double> nthSquareRoot = iterate(Math::sqrt, 2);
Run Code Online (Sandbox Code Playgroud)
以及iterate方法的签名:
public static <X, Y extends X> Function<X, ? extends X> iterate(Function<X, Y> function, int n)
Run Code Online (Sandbox Code Playgroud)
例:
public static <X, Y extends X> Function<X, ? extends X> iterate(Function<X, Y> function, int n) {
if (n < 0) return null;
if (n == 0) return Function.identity();
Function<X, Y> iteration = Objects.requireNonNull(function);
for (; n > 1; --n) {
iteration = composite(function, iteration);
}
return iteration;
}
public static void main(String[] args) {
Function<Double, ? extends Double> nthSquareRoot = iterate(Math::sqrt, 2);
System.out.println(nthSquareRoot.apply(81d));
}
Run Code Online (Sandbox Code Playgroud)
按预期打印9.
或者你可以使用UnaryOperator:
public static <X> UnaryOperator<X> iterate(UnaryOperator<X> function, int n) {
if (n < 0) return null;
if (n == 0) return UnaryOperator.identity();
UnaryOperator<X> iteration = Objects.requireNonNull(function);
for (int i = 0; i < n - 1; i++) {
iteration = composite(function::apply, iteration::apply)::apply;
}
return iteration;
}
public static void main(String[] args) {
UnaryOperator<Double> nthSquareRoot = iterate(Math::sqrt, 2);
System.out.println(nthSquareRoot.apply(81d));
}
Run Code Online (Sandbox Code Playgroud)