我需要创建一个帮助方法,允许创建任何Iterable<?的总和extends Number>,因为我们有很多向量并且需要一个快速方法来确定总和,所以我创建了以下方法:
static Integer sum(Iterable<Integer> it) {
Integer result = 0;
for(T next : it) {
result += next;
}
return result;
}
此方法仅适用于int,但我们也有双打和长。因为你不能有两个具有相同签名的方法(我们的编译器认为整数和(Iterable&lt; Integer&gt;)具有与Double sum(Iterable&lt; Double&gt;)相同的签名。)我尝试用泛型编写一个方法。
private static <T extends Number> T sum(Iterable<? extends T> it) {
T result;
for(T next : it) {
result += next;
}
return result;
}
但是这个方法不会编译(原因:对于Object,Object,运算符+ =未定义)。我能在这做什么?我知道在C ++中你可以重载运算符,但不能用Java重载。但扩展Number的每个类都会使+ =运算符重载。我能在这做什么?
提前谢谢。
答案 0 :(得分:2)
如果这些数字不能是BigInteger
或BigDecimal
s,您可以尝试将它们转换为double
s并将其相加:
double result = 0;
for (T number : it) {
result += number.doubleValue();
}
答案 1 :(得分:0)
看一看 How to add two java.lang.Numbers?
您不知道所用数字的类型,因此如果您可以容忍精度损失,请使用next.doubleValue(),或者如果您想保持精度,请使用BigDecimal(使用String构造函数)。
答案 2 :(得分:0)
您的方法与java.lang.Integer
一起使用的原因是auto-boxing。
不幸的是,java.lang.Number
是一个非常一般意义上的数值的表示,特别是你将它的值作为具体的数字类型之一,但不能用它做很多其他事情。
在您的情况下,这意味着您将为每个对您重要的返回类型设置 sum 方法。
基本上你会得到这样的东西(假设你想要将浮点数加到非浮点格式时将其舍入):
public class SumUtils
{
public static Integer sumToInteger(Iterable<Number> numbers)
{
long sum = 0;
for (Number number : numbers)
{
sum += Math.round(number.doubleValue());
}
if (sum > Integer.MAX_INT)
{
throw new IllegalStateException();
}
return (int)sum;
}
public static Long sumToLong(Iterable<Number> numbers)
{
long sum = 0;
for (Number number : numbers)
{
sum += Math.round(number.doubleValue());
}
return sum;
}
public static Float sumToFloat(Iterable<Number> numbers)
{
double sum = 0;
for (Number number : numbers)
{
sum += number.doubleValue();
}
if (sum > Float.MAX_FLOAT)
{
throw new IllegalStateException();
}
return (float)sum;
}
public static Double sumToDouble(Iterable<Number> numbers)
{
double sum = 0;
for (Number number : numbers)
{
sum += number.doubleValue();
}
return sum;
}
public static BigDecimal sumToBigDecimal(Iterable<Number> numbers)
{
BigDecimal sum = BigDecimal.ZERO;
for (Number number : numbers)
{
if (number instanceof BigDecimal)
{
sum = sum.add((BigDecimal)number);
}
else
{
sum = sum.add(new BigDecimal(number.doubleValue()));
}
}
return sum;
}
}
答案 3 :(得分:0)
如果所有数字都是相同(未知)类型,那么您不需要检查每个元素,只需获取第一个类型并选择相应的循环来计算double
中的和,{{1 }},long
或BigDecimal
。
答案 4 :(得分:0)
您可以尝试instanceof检查,然后在每次迭代时进行转换 Lame解决方案,如何
private static <T extends Number> T sum(Iterable<? extends T> it)
{
T result = null;
Integer inttt = null;
if (it.iterator()
.hasNext() && it.iterator()
.next() instanceof Integer)
{
for (T next : it)
{
if (next instanceof Integer)
{
inttt += (Integer) next;
}
}
return (T)inttt;
}
// For other types here
return result;
}
答案 5 :(得分:0)
所以我现在写了以下内容,但我并不十分满意......
static <T extends Number> T sum(Iterable<? extends T> it) {
Iterator<? extends T> iterator = it.iterator();
Number first = iterator.next();
if(first instanceof Integer) {
Integer _result = (Integer) first;
for(T next : it)
_result+=(Integer)next;
return (T) _result;
}
else if(first instanceof Double) {
Double _result = (Double) first;
for(T next : it)
_result+=(Double)next;
return (T) _result;
}
else if(first instanceof Long) {
Long _result = (Long) first;
for(T next : it)
_result+=(Long)next;
return (T) _result;
}
else if(first instanceof Float) {
Float _result = (Float) first;
for(T next : it)
_result+=(Float)next;
return (T) _result;
}
else if(first instanceof Byte) {
Byte _result = (Byte) first;
for(T next : it)
_result= (byte)(_result + (Byte)next);
return (T) _result;
}
else if(first instanceof Short) {
Short _result = (Short) first;
for(T next : it)
_result= (short)(_result + (Short)next);
return (T) _result;
}
else if(first instanceof java.math.BigInteger) {
java.math.BigInteger _result = (java.math.BigInteger) first;
for(T next : it)
_result=((java.math.BigInteger)next).add((BigInteger) next);
return (T) _result;
}
else if(first instanceof java.math.BigDecimal) {
java.math.BigDecimal _result = (java.math.BigDecimal) first;
for(T next : it)
_result=((java.math.BigDecimal)next).add((BigDecimal) next);
return (T) _result;
}
else {
throw new IllegalArgumentException(I18n._(String.format("Type %s not supported."), first.getClass()));
}
}