2012-05-28 236 views
32

我在嘗試使用下面的代碼來計算用戶輸入的一組值並將其顯示在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(); 
    } 

代碼有什麼問題?

+5

你是不是總結的痕跡,你的總結數組索引'i'。 –

回答

57

爲什麼在使用增強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; 
} 
+23

+1這是一個更文明的時代的文明循環。它不像笨拙一樣笨拙或隨意。 –

+0

+1正好寫完了。 – n00begon

+5

我會檢查是否marks.size()== 0在開始,因爲這將除以零,如果列表如果爲空 – Axarydax

9
sum += i; 

您正在添加索引;你應該將實際的項目中ArrayList

sum += marks.get(i); 

同時,爲了確保返回值不會被截斷,力一個操作數double,改變你的方法簽名double

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

@Cicada:謝謝!只是編輯它。 – Ryan

+3

因爲他正在使用一個列表,所以應該使用'sum + = marks.get(i);' – jahroy

10

使用一個雙數的總和,否則你正在做一個整數除法,你不會得到任何小數:

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 stream API:

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

在返回之前等待一個double值會更乾淨,所以你不會有任何浮動當標記是一個非常大的列表時,點錯誤會蔓延。關於Java 8 API的 – n00begon

+0

需要導入什麼? – eactor

+0

@ector在上面的示例中,不需要額外的導入。 –

40

與Java 8是a bit easier

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

因此您的平均值爲average.getAsDouble()

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

'average.isPresent()? average.getAsDouble():defaultValue'可以進一步簡化爲'optional.orElse(defaultValue)' –

0

這裏它採用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; 
} 
1

正確,快速地計算平均爲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

它協同工作對於列表,因爲任何列表包含少於2^31 int,並且可以使用long作爲累加器。

PS

事實上的foreach分配內存 - 你應該在任務使用舊樣式()循環的關鍵部件

12

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

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

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

這具有沒有移動部件的優點。通過改變地圖方法調用,它可以很容易地適用於其他類型的對象列表。

例如與雙打:

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().getAsDouble(); 

或BigDecimals的:

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().getAsDouble(); 
+0

oops - 從未注意到上面的Java8答案與我在例2中給出 – robjwilkins

+0

的答案相同,爲什麼mapToDouble需要dblList包含雙精度? – simpleuser

1

使用Guava,它得到語法簡化:

Stats.meanOf(numericList); 
1

您可以使用標準的循環結構或迭代器/ 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()); 

參考:Calculating average of arraylist

0
List.stream().maptodouble(a->a).Average() 
+0

嘗試使用代碼格式併爲您的答案提供一些上下文。 查看其他答案作爲示例。 – hidralisk