I've been playing with a statistical Sample object for an input/output model during the course of my machine learning class. I wanted to expand the functionality to add quadratic fit by least squares method, but I want to make sure the functionality is thus far is up to par before improving it further. Mainly just looking for feedback, improvements, comments, anything!
package statTool;
import java.util.ArrayList;
import javafx.util.Pair;
/**
 * This class is used to model a data sampled from a standard distribution, and computes several values used
 * to analyze the behavior of the population to which the sample belongs.
 * The values computed and retained for both input and output are:
 *      Mean
 *      Min/Max 
 *      Sum of Squared Error
 *      Mean Squared Error(Variance)
 *      Standard Deviation (Standard Error)
 *      Sum
 *      Square Sum
 *Singular Variables are:
 *      R correlation
 *      Linear fit equation
 *      input*output Product Sum  
 * @author B19635
 */
public class XYSample {
        float size;
        float xMean, xMin, xMax, xVariance, xError, xSumSquaredError;
        float yMean, yMin, yMax, yVariance, yError, ySumSquaredError;
        float xSum, ySum, xySum, x2Sum, y2Sum;
        float R;
        LinearEquation fitFunction;
        ArrayList<Float> X, Y;
        //--------------------------------------------------------------------------------------------------------------
        // Constructors
        // --------------------------------------------------------------------------------------------------------------
        public XYSample() {
            initSample();
        }
        public XYSample(ArrayList<Pair<Float, Float>> data){
            initSample(); 
            addValues(data);
        }
        public XYSample(ArrayList<Float> xData, ArrayList<Float> yData) {
            initSample();
            addValues(xData, yData);
        }
        private void initSample(){
            size = 0;
            //Initialize List
            X = new ArrayList<Float>();
            Y = new ArrayList<Float>();
            //Initialize comparator values
            xMin = Float.MAX_VALUE;
            yMin = Float.MAX_VALUE;
            xMax = Float.MIN_VALUE;
            yMax = Float.MIN_VALUE;
        }
        //--------------------------------------------------------------------------------------------------------------
        //      Populate Sample
        //--------------------------------------------------------------------------------------------------------------
        //As the above suggests, the below methods serve to extract values from ArrayLists and add them to the 
        //appropriate input or output list
        /**
         * Splits pairData into two lists of input and output then calls addValues
         * @param toAdd
         */
        public void addValues(ArrayList<Pair<Float,Float>> toAdd) {
            ArrayList<Float> input = new ArrayList<Float>();
            ArrayList<Float> output = new ArrayList<Float>();
            for(int i = 0; i < toAdd.size(); i++){
                input.add(toAdd.get(i).getKey());
            }
            for(int i = 0; i < toAdd.size(); i++){
                output.add(toAdd.get(i).getValue());
            }
            addValues(input, output);
        }
        /**
         * This method allows the user to add additional values to the existing data set
         * Checks for new max or min now, to avoid iterating through the entire input/output set needlessly,
         * then calls setValues() to recalculate sample analysis
         * @param toAdd
         */
        public void addValues(ArrayList<Float> input, ArrayList<Float> output) {
            X.addAll(input);
            Y.addAll(output);
            //Check input minimum and maximum
            float temp;
            for(int i = 0; i < input.size(); i++){
                temp = input.get(i);
                if(temp > xMax){
                    xMax = temp;
                }
                if(temp < xMin){
                    xMin = temp;
                }
            }
            //Check output minimum and maximum
            for(int i = 0; i < output.size(); i++){
                temp = output.get(i);
                if(temp > yMax){
                    yMax = temp;
                }
                if(temp < yMin){
                    yMin = temp;
                }
            }
            setValues();
        }
        //--------------------------------------------------------------------------------------------------------------
        //      Basic Analysis
        //--------------------------------------------------------------------------------------------------------------
        //The method below is called every time the sample is changed. It initializes each basic analytical value
        private void setValues() {
            size = (float)X.size();
            xMean = computeMean(X);
            yMean = computeMean(Y);
            xSumSquaredError = computesquaredError(X, xMean);
            ySumSquaredError = computesquaredError(Y, yMean);
            xVariance = computeVariance(xSumSquaredError);
            yVariance = computeVariance(ySumSquaredError);
            xError = computeStandardError(xSumSquaredError);
            yError = computeStandardError(ySumSquaredError);
            xSum = computeSum(X);
            ySum = computeSum(Y);
            x2Sum = computeSquareSum(X);
            y2Sum = computeSquareSum(Y);
            xySum = computeProductSum(X,Y);
            R = computeCorrelation();
            fitFunction = computeLinearFit();
        }
        /**
         * Computes the Sample Mean by creating a running summation of the values and then dividing by the
         * number of values in the set
         * @return double
         */
        private Float computeMean(ArrayList<Float> data) {
            float runSum = 0;
            for (float value: data) {
                runSum += value;
            }
            return runSum / size;
        }
        /**
         * Computes the Sum of the Squared Error for the sample, which is used to compute the variance and 
         * standard error
         * @return double
         */
        private float computesquaredError(ArrayList<Float> data, float mean){
            float temp;
            float tempSum = 0;
            for (float value: data) {
                temp = (float) Math.pow(value - mean, 2);
                tempSum += temp;
            }
            return tempSum;
        }
        /**
         * The sample variance carries a bias of n-1/n, where n is the size of the sample. Multiplying this values 
         * by n/n-1 removes this bias as an estimate of the population variance. This results in the variance 
         * being calculated with n-1 as opposed to n
         * @return double
         */
        private float computeVariance(float sumsquaredError) {
            return sumsquaredError / (size-1);
        }
        /**
         * As a population estimate, the samples standard error carries a bias of (sqrt(n-1.5)/sqrt(n)). Removing
         * this bias, as above with variance, results in calculating with sqrt(n-1.5) as the denominator
         * @return
         */
        private float computeStandardError(float sumSquaredError){
            return (float) Math.sqrt(sumSquaredError / (size-1.5));
        }
        //--------------------------------------------------------------------------------------------------------------
        //      Summations
        //--------------------------------------------------------------------------------------------------------------
        //The methods below return summations of the given data
        private float computeSum(ArrayList<Float> data){
            float tempSum = 0;
            for(int i = 0; i < data.size(); i++){
                tempSum += data.get(i);
            }
            return tempSum;
        }
        private float computeProductSum(ArrayList<Float> data1, ArrayList<Float> data2){
            float tempSum = 0;
            for(int i = 0; i < data1.size(); i++){
                tempSum += (data1.get(i)* data2.get(i));
            }
            return tempSum;
        }
        private float computeSquareSum(ArrayList<Float> data){
            float tempSum = 0;
            for(int i = 0; i < data.size(); i++){
                tempSum += Math.pow(data.get(i), 2);
            }
            return tempSum;
        }
        //--------------------------------------------------------------------------------------------------------------
        //      Regression Analysis
        //--------------------------------------------------------------------------------------------------------------        
        //The methods below perform regression on the samples input and output to compute a linear equation
        //of form Slope*(input) + Intercept = (output). R^2 correlation is returned as a decimal between 0 and 1
        private float computeCorrelation(){
            float numerator = (X.size() * xySum) - (xSum * ySum);
            float denominatorLeft = (X.size() * x2Sum) - ((float)Math.pow(xSum, 2));
            float denominatorRight = (Y.size() * y2Sum) - ((float)Math.pow(ySum, 2));
            return numerator/((float)Math.sqrt(denominatorLeft*denominatorRight));  
        }
        private LinearEquation computeLinearFit(){          
            float slope = computeSlope(xySum, xSum, ySum, x2Sum);
            float intercept = computeIntercept(xySum, xSum, ySum, x2Sum);
            LinearEquation toReturn = new LinearEquation(slope, intercept);
            return toReturn;
        }
        private float computeSlope(float xySum, float xSum, float ySum, float x2Sum) {
            float numerator = (X.size()*xySum) - (xSum*ySum);
            float denominator = (X.size()*x2Sum) - (float)Math.pow(xSum, 2);
            return numerator/denominator;
        }
        private float computeIntercept(float xySum, float xSum, float ySum, float x2Sum) {
            float numerator = (ySum*x2Sum) - (xSum*xySum);
            float denominator = (X.size()*x2Sum) - (float)Math.pow(xSum, 2);
            return numerator/denominator;
        }
        //--------------------------------------------------------------------------------------------------------------
        //      Getters
        //--------------------------------------------------------------------------------------------------------------
        public float getSize(){return size;}
        public float getXMean(){return xMean;}
        public float getYMean(){return yMean;}
        public float getXMin(){return xMin;}
        public float getYMin(){return yMin;}
        public float getXMax(){return xMax;}
        public float getYMax(){return yMax;}
        public float getXVariance(){return xVariance;}
        public float getYVariance(){return yVariance;}
        public float getXError(){return xError;}
        public float getYError(){return yError;}
        public float getXSumsquaredError(){return xSumSquaredError;}
        public float getYSumsquaredError(){return ySumSquaredError;}
        public float getXSum(){return xSum;}
        public float getYSum(){return ySum;}
        public float getXSquareSum(){return x2Sum;}
        public float getYSquareSum(){return y2Sum;}
        public float getProductSum(){return xySum;}     
        public float getR(){return R;}
        public float getRSquare(){return (float)Math.pow(R,2);}
        public LinearEquation getLinearFit(){return fitFunction;}
    }
public class LinearEquation {
    float slope, intercept;
    public LinearEquation(float slope, float intercept) {
        this.slope = slope;
        this.intercept = intercept;
    }
    public float f(float input){
        return (input * slope) + intercept;
    }
    public float getSlope(){
        return slope;
    }
    public float getIntercept(){
        return intercept;
    }
}
