I\'m trying to use the below code to calculate the average of a set of values that a user enters and display it in a jTextArea
but it does not work properly. Sa
Why use a clumsy for loop with an index when you have the enhanced for loop?
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;
}
Use a double for the sum, otherwise you are doing an integer division and you won't get any decimals:
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();
}
or using the Java 8 stream API:
return marks.stream().mapToInt(i -> i).average().orElse(0);
Using Guava, it gets syntactically simplified:
Stats.meanOf(numericList);
Correct and fast way compute average for 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();
}
This solution take into account:
It works coorectly for List, because any list contains less that 2^31 int, and it is possible to use long as accumulator.
PS
Actually foreach allocate memory - you should use old style for() cycle in mission critical parts
Here a version which uses BigDecimal
instead of 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;
}
With Java 8 it is a bit easier:
OptionalDouble average = marks
.stream()
.mapToDouble(a -> a)
.average();
Thus your average value is average.getAsDouble()
return average.isPresent() ? average.getAsDouble() : 0;