java - 添加任意 Number 类变量
问题描述
我想总结一个Number
对象列表,并且每个对象只使用实际值(如果它是一个Integer
我只想使用.intValue()
方法而不是.doubleValue
ex..),我不想使用instanceof
.
返回值必须是Number
类型。
我如何使用双重调度或策略模式或类似的东西来做到这一点?
我不能扩展每个实现类,Number
也不能对两个Number
变量求和。
里面只有 6.xValue()
种方法Number
,我想相应地使用它们中的每一种。
解决方案
由于实际返回的类型与调用者相关,并且由于声明的类型为 而不明显时对调用者没有多大用处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);
请注意,Java 的Number
类型层次结构并不反映原始类型的类型转换规则。因此,虽然int
和long
值的混合可以处理为whilelong
混合int
并且double
需要使用以防止精度损失,但混合和与混合和double
之间没有区别,两者都只是不同子类型的混合。因此,无论哪种情况,您都需要在两者之间进行转换,无论实际组合如何,任何转换都将在没有警告的情况下编译,即使它意味着精度损失。Integer
Long
Integer
Double
Number
Number::xxxValue
Number::xxxValue
由于大long
值在转换为 时可能会丢失精度double
,因此最后一个示例使用中间String
值,以确保在存在long
和double
输入值的情况下,所有转换为BigDecimal
无损。
推荐阅读
- scala - 在具有协变类型的 Scala 参数化类中实现方法
- python - 获取相关模型的数量
- c++ - 关于包含新课程的基本 cmake 问题
- javascript - Google Maps API - 基于复选框状态的 loadGeoJson
- java - Recyclerview 在“搜索”或“过滤”之后不是“排序”
- r - 使用 cpp 代码编译和链接 R 包时出现奇怪的 SHLIB 行为
- asp.net-core - ASP.NET Core 中每页的权限
- qt - Qt - 如何使用带参数的 SQL SELECT COUNT?
- python - scrapy 和 selenium 似乎相互干预
- ios - 组合不同的 UIView 类