3
\$\begingroup\$

So I'm supposed to calculate variance based on this forumula through functional programming:

$$\sigma^2 = \frac{\sum\limits_{i=0}^{n-1} (X -\mu)^2}{n-1}$$

This is the code that works:

public static double variance1(int[] array)
{
     double mean=mean(array);
     double summation=DoubleStream.iterate(0,idx->idx+1)
                                  .limit(array.length)
                                  .reduce(0,(summation_counter,idx)->
                                   {
                                     return Math.pow(array[(int)idx]-mean, 2)+summation_counter;
                                   });
                                  
                               
     return summation/(array.length-1);
}

Although the code works, it's ugly with the typecasts and seems forced.

Initially, I thought of doing something like

double summation=IntStream.rangeClosed(0,array.length-1)
                          .reduce(0, (summation_counter,idx)-> ....

but I couldn't use an IntStream as the body of the reduce method returns double.

\$\endgroup\$

2 Answers 2

3
\$\begingroup\$

First off, watch your formating. Java standard is to have spaces around operators, and a space after commas. In the reduce lambda you can leave out the return and the braces, just like you did't for iterate.

It's a bit ugly to use a DoubleStream for the array indices, and number streams provide a sum() method, so using reduce is unnecessary.

An array can easily streamed using Arrays.stream(), which produces an IntStream and with mapToDouble a DoubleStream can be created:

double summation = Arrays.stream(array)
                     .mapToDouble(x -> (x - mean) * (x - mean))
                     .sum();
\$\endgroup\$
1
\$\begingroup\$

In my opinion, there's no other way to return a double with the reduce and have an int value as the index without casting; it's either integer or double.

For the rest of the code, here is some advice.

Add checks for empty / null on the array.

In my opinion, it's always a good thing to verify the validity of the array parameter before handling it (not null, and have at least one element in this case).

Use the multiplication operator instead of Math.Pow

The Math.Pow tend to be slower in some case when compared with the multiplication operator. In my opinion, it's best to use the multiplication operator when the exponent < 5.

\$\endgroup\$
2
  • \$\begingroup\$ Do you think using Optional<Double> or null checking on the array is better? \$\endgroup\$
    – Leon
    Dec 14, 2020 at 0:17
  • \$\begingroup\$ To clarify, I was talking of adding a condition that check if the array parameter is valid (not null & size > 0); this condition should be before the call of the method mean. This condition will prevent invalid parameters of reaching your code. \$\endgroup\$
    – Doi9t
    Dec 14, 2020 at 0:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.