Cham - 1 year ago 147
Java Question

# Mean, Median and Mode

Hi I'm having problem with my codes on the Modal value. Here is my code:

``````public class basicStatistics {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt();
int[] arr = new int[n];
int[] arrCount = new int[n];
int maxCount = 0;
double median = 0.0, mean = 0.0;
for(int i = 0; i < n; i++) {
arr[i] = in.nextInt();
mean = mean + arr[i];
}
mean = mean/n;
for(int i = 0; i < n; i++) {
for(int j = 0; j < n; j++){
if(arr[i] == arr[j]){
arrCount[i]++;
}
if(maxCount < arrCount[i])
maxCount = i;
}
}
Arrays.sort(arr);
if(n%2 == 0) {
median = arr[n/2] + arr[n/2-1];
median = median/2;
} else {
median = arr[n/2];
}
System.out.printf("%.1f\n", mean);
System.out.printf("%.1f\n", median);
System.out.println(arr[maxCount]);
}
}
``````

The issue is I can't get the Modal value right when the input is this: http://pastebin.com/HCqTrimY I used pastebin as it inputs 2500 numbers. My code outputs the array value 259 instead of 2184 for Mode however if the input is n = 10 and the numbers = 64630 11735 14216 99233 14470 4978 73429 38120 51135 67060 I get the mode value correct or for other scenario.

I also wanted to transform the code to a more efficient one utilizing the Java8 structure. Thank you in advanced!

If you want to use Java 8, you can make that code a lot shorter. First, the `mean`: Here you can create a `stream` from your `int`-array `arr` and then just call the `average` method:

``````double mean = IntStream.of(arr).average().getAsDouble();
``````

The `median` is pretty much the same as in your code; I just put it on fewer lines by using a ternary expression (`... ? ... : ...`) instead of a multi-line `if/else`:

``````Arrays.sort(arr);
int len = arr.length;
double median = len % 2 == 0 ? (arr[len/2-1] + arr[len/2]) / 2. : arr[len/2];
``````

The `mode` is a bit more difficult, last but not least since you seem to need the smallest mode in case there are multiple numbers appearing most often. While your double-`for`-loop approach would work, too, it has quadratic complexity, which could become a problem for larger data sets. Instead, you should use a `Map` to count the different numbers. In Java 8, this can be done very easily using `Collectors.groupingBy` and `Collectors.counting`. Then, just determine the `max` of the counts, `filter` the numbers that have that count, and get the `min` of those.

``````Map<Integer, Long> counts = IntStream.of(arr).boxed()
.collect(Collectors.groupingBy(x -> x, Collectors.counting()));
Long max = counts.values().stream().max(Comparator.naturalOrder()).get();
int mode = counts.entrySet().stream()
.filter(e -> e.getValue().equals(max))
.min(Comparator.comparing(Entry::getKey)).get().getKey();
``````
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download