Java 1.7:Iterable的总和<t extends =“”number =“”> </t>

时间:2014-01-06 12:30:01

标签: java numbers sum iterable

我需要创建一个帮助方法,允许创建任何Iterable&lt;?的总和extends Number&gt;,因为我们有很多向量并且需要一个快速方法来确定总和,所以我创建了以下方法:

 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的每个类都会使+ =运算符重载。我能在这做什么?

提前谢谢。

6 个答案:

答案 0 :(得分:2)

如果这些数字不能是BigIntegerBigDecimal 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 }},longBigDecimal

答案 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()));
    }
}