计算一个数组列表的平均?(Calculating average of an array list?

2019-06-24 21:48发布

我尝试使用下面的代码来计算一组用户输入值的平均值,并在显示它jTextArea ,但它不能正常工作。 比方说,一个用户输入7,4,和5,程序将显示1当它应该显示5.3的平均

  ArrayList <Integer> marks = new ArrayList();
  Collections.addAll(marks, (Integer.parseInt(markInput.getText())));

  private void analyzeButtonActionPerformed(java.awt.event.ActionEvent evt) {
      analyzeTextArea.setText("Class average:" + calculateAverage(marks));
  }

  private int calculateAverage(List <Integer> marks) {
      int sum = 0;
      for (int i=0; i< marks.size(); i++) {
            sum += i;
      }
      return sum / marks.size();
  }

什么是错的代码?

Answer 1:

为什么要使用一个笨拙的for循环与索引当你有增强的for循环?

private double calculateAverage(List <Integer> marks) {
  Integer sum = 0;
  if(!marks.isEmpty()) {
    for (Integer mark : marks) {
        sum += mark;
    }
    return sum.doubleValue() / marks.size();
  }
  return sum;
}


Answer 2:

与Java 8是一个更容易一点 :

OptionalDouble average = marks
            .stream()
            .mapToDouble(a -> a)
            .average();

因此,你的平均值为average.getAsDouble()

return average.isPresent() ? average.getAsDouble() : 0; 


Answer 3:

如果使用Java8您可以从列表获取值的平均值如下:

    List<Integer> intList = Arrays.asList(1,2,2,3,1,5);

    Double average = intList.stream().mapToInt(val -> val).average().orElse(0.0);

这有没有移动部件的优势。 它可以很容易地适合于通过改变地图的方法调用与其它类型的对象的列表的工作。

例如与双打:

    List<Double> dblList = Arrays.asList(1.1,2.1,2.2,3.1,1.5,5.3);
    Double average = dblList.stream().mapToDouble(val -> val).average().orElse(0.0);

NB。 mapToDouble是必需的因为它返回其具有一个DoubleStream average方法,同时使用map不。

或BigDecimals的:

@Test
public void bigDecimalListAveragedCorrectly() {
    List<BigDecimal> bdList = Arrays.asList(valueOf(1.1),valueOf(2.1),valueOf(2.2),valueOf(3.1),valueOf(1.5),valueOf(5.3));
    Double average = bdList.stream().mapToDouble(BigDecimal::doubleValue).average().orElse(0.0);
    assertEquals(2.55, average, 0.000001);
}

使用orElse(0.0)消除了与择对象问题从返回的average是“不存在”。



Answer 4:

使用双的总和,否则你正在做一个整数除法,你不会得到任何小数:

private double calculateAverage(List <Integer> marks) {
    if (marks == null || marks.isEmpty()) {
        return 0;
    }

    double sum = 0;
    for (Integer mark : marks) {
        sum += mark;
    }

    return sum / marks.size();
}

或使用Java 8流API:

    return marks.stream().mapToInt(i -> i).average().orElse(0);


Answer 5:

sum += i;

您要添加的指标; 你应该添加在实际项目ArrayList

sum += marks.get(i);

同时,为了确保返回值不会被截断,力一个操作数double ,改变你的方法签名,以double

return (double)sum / marks.size();


Answer 6:

使用番石榴 ,它被语法简化为:

Stats.meanOf(numericList);


Answer 7:

List.stream().mapToDouble(a->a).average()


Answer 8:

正确而快速的方式计算平均值List<Integer>

private double calculateAverage(List<Integer> marks) {
    long sum = 0;
    for (Integer mark : marks) {
        sum += mark;
    }
    return marks.isEmpty()? 0: 1.0*sum/marks.size();
}

该解决方案考虑到:

  • 处理溢出
  • 不分配内存喜欢Java8流
  • 不要使用慢速的BigDecimal

它的工作原理为coorectly名单,因为任何列表包含少于2 ^ 31 INT,并且可以使用,只要蓄电池。

PS

实际上的foreach分配内存 - 你应该在任务关键部位使用旧样式()循环



Answer 9:

您可以使用标准的循环结构或迭代器/的ListIterator对于相同的:

List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8);
double sum = 0;
Iterator<Integer> iter1 = list.iterator();
while (iter1.hasNext()) {
    sum += iter1.next();
}
double average = sum / list.size();
System.out.println("Average = " + average);

如果使用Java 8中,您可以使用Stream或IntSream操作的一样:

OptionalDouble avg = list.stream().mapToInt(Integer::intValue).average();
System.out.println("Average = " + avg.getAsDouble());

参考: 计算的ArrayList平均



Answer 10:

在这里,它使用一个版本BigDecimal ,而不是double

public static BigDecimal calculateAverage(final List<Integer> values) {
    int sum = 0;
    if (!values.isEmpty()) {
        for (final Integer v : values) {
            sum += v;
        }
        return new BigDecimal(sum).divide(new BigDecimal(values.size()), 2, RoundingMode.HALF_UP);
    }
    return BigDecimal.ZERO;
}


Answer 11:

号码列表并不大,一切都显得恰到好处。 但是,如果它不是,十分谨慎,需要实现的正确性/准确性

双榜为例:

如果列表是不太大的,你可以试试这个:

doubles.stream().mapToDouble(d -> d).average().orElse(0.0);

但是,如果它是在你的控制和相当大的,你必须把为BigDecimal如下(使用BigDecimal的答案其实是错误的方法):

doubles.stream().map(BigDecimal::valueOf).reduce(BigDecimal.ZERO, BigDecimal::add)
       .divide(BigDecimal.valueOf(doubles.size())).doubleValue();

附上我进行了论证我的观点测试

    @Test
    public void testAvgDouble() {
        assertEquals(5.0, getAvgBasic(Stream.of(2.0, 4.0, 6.0, 8.0)), 1E-5);
        List<Double> doubleList = new ArrayList<>(Arrays.asList(Math.pow(10, 308), Math.pow(10, 308), Math.pow(10, 308), Math.pow(10, 308)));
        // Double.MAX_VALUE = 1.7976931348623157e+308
        BigDecimal doubleSum = BigDecimal.ZERO;
        for (Double d : doubleList) {
            doubleSum =  doubleSum.add(new BigDecimal(d.toString()));
        }
        out.println(doubleSum.divide(valueOf(doubleList.size())).doubleValue());
        out.println(getAvgUsingRealBigDecimal(doubleList.stream()));
        out.println(getAvgBasic(doubleList.stream()));
        out.println(getAvgUsingFakeBigDecimal(doubleList.stream()));
    }

    private double getAvgBasic(Stream<Double> doubleStream) {
        return doubleStream.mapToDouble(d -> d).average().orElse(0.0);
    }

    private double getAvgUsingFakeBigDecimal(Stream<Double> doubleStream) {
        return doubleStream.map(BigDecimal::valueOf)
                .collect(Collectors.averagingDouble(BigDecimal::doubleValue));
    }

    private double getAvgUsingRealBigDecimal(Stream<Double> doubleStream) {
        List<Double> doubles = doubleStream.collect(Collectors.toList());
        return doubles.stream().map(BigDecimal::valueOf).reduce(BigDecimal.ZERO, BigDecimal::add)
                .divide(valueOf(doubles.size()), BigDecimal.ROUND_DOWN).doubleValue();
    }

至于IntegerLong ,相应地可以使用BigInteger类似。



文章来源: Calculating average of an array list?