因为实际返回的类型与调用者相关,并且由于声明的
Number
,它应该在调用者的控制下,并与泛型类型签名相结合,从而允许调用者实际使用特定的返回类型。例如。
public static <N extends Number, R extends Number> R sum(
List<? extends N> input, Function<? super N, ? extends R> cast,
BinaryOperator<R> addition) {
return input.stream().<R>map(cast).reduce(addition).orElse(null);
}
public static <N extends Number> N sum(
List<? extends N> input, BinaryOperator<N> addition) {
return sum(input, Function.identity(), addition);
}
这允许请求计算在输入类型内,例如。
List<Integer> list = Arrays.asList(1, 2, 3, 4);
Integer iSum1 = sum(list, Integer::sum);
Integer iSum2 = sum(list, Math::addExact);//throw on overflow
但在总结之前还要扩大类型:
Long lSum = sum(list, Integer::longValue, Long::sum);
同样地,你可以处理
Long
或
Double
输入类型:
List<Long> list = Arrays.asList(1L, 2L, 3L, 4L);
Long lSum1 = sum(list, Long::sum);
Long lSum2 = sum(list, Math::addExact);//throw on overflow
// without precision loss:
BigInteger biSum = sum(list, BigInteger::valueOf, BigInteger::add);
List<Double> list = Arrays.asList(1.0, 2.0, 3.0, 4.0);
Double dSum = sum(list, Double::sum);
// without precision loss:
BigDecimal bdSum = sum(list, BigDecimal::valueOf, BigDecimal::add);
或者处理混合类型:
List<Number> list = Arrays.asList(1, 2L, 3.0, 4F);
Double dSum = sum(list, Number::doubleValue, Double::sum);
BigDecimal bdSum = sum(list, n -> new BigDecimal(n.toString()), BigDecimal::add);
注意Javas
数字
类型层次结构不反映基元类型的类型转换规则。所以当
int
和
long
值可以作为
长的
而混合
智力
和
double
需要使用
双重的
为了防止精度损失,混合和混合之间没有区别
Integer
和
长的
与混合
整数
和
双重的
,两者都只是不同文化的混合体
数字
亚型。所以无论哪种情况,你都需要
Number::xxxValue
在两者之间转换,无论实际组合如何,任何
编号:xxxValue
转换将在没有警告的情况下编译,即使它意味着精度损失。
自大
长的
值在转换为时可能会失去精度
双重的
最后一个例子使用了一个中间词
String
价值,以确保
长的
和
双重的
输入值,所有转换为
BigDecimal
它们是无损的。