Skip to main content
Bumped by Community user
Bumped by Community user
replaced http://codereview.stackexchange.com/ with https://codereview.stackexchange.com/
Source Link
Source Link
coderodde
  • 32.3k
  • 15
  • 79
  • 205

A value set data structure for rapid statistics queries in Java - follow-up

(See the previous iteration.)

Now all operations of the data structure work in exact constant time, yet it came with the price: the state of this set maybe non-sensical. A user may end up with the set with negative number of elements in it. Basically, the client programmer must keep track of how he/she work with this set.

StatisticsNumberSet.java

package net.coderodde.stat;

/**
 * This class provides the means for rapid statistics queries.
 * 
 * @author Rodion "rodde" Efremov
 * @version 1.618 (Mar 28, 2017)
 */
public class StatisticsNumberSet {

    /**
     * Holds the sum of all elements in this set.
     */
    private double sum;

    /**
     * Holds the sum of square of each element in this set.
     */
    private double squareSum;

    /**
     * Holds the number of elements currently in this set.
     */
    private int size;

    /**
     * Adds the given number to this set.
     * 
     * @param number the number to add.
     */
    public void add(double number) {
        checkNumberIsFinite(number);
        sum += number;
        squareSum += number * number;
        size++;
    }

    /**
     * Converts and adds the given number to this set.
     * 
     * @param number the number to add.
     */
    public void add(Number number) {
        add(number.doubleValue());
    }

    /**
     * Removes the given number from this set.
     * 
     * @param number the number to remove.
     */
    public void remove(double number) {
        checkNumberIsFinite(number);
        sum -= number;
        squareSum -= number * number;
        size--;
    }

    /**
     * Converts and removes the given number from this set.
     * 
     * @param number the number to remove.
     */
    public void remove(Number number) {
        remove(number.doubleValue());
    }

    /**
     * Resets the state of this set to an empty set.
     */
    public void clear() {
        sum = 0.0;
        squareSum = 0.0;
        size = 0;
    }

    /**
     * Returns the number of elements in this set.
     * 
     * @return the size of this set.
     */
    public int size() {
        return size;
    }

    /**
     * Computes the average of this set.
     * 
     * @return the average.
     */
    public double getAverage() {
        return sum / size;
    }

    /**
     * Computes the variance of this set.
     * 
     * @return the variance. 
     */
    public double getVariance() {
        double step1 = squareSum - sum * sum / size;
        return step1 / (size - 1);
    }

    /**
     * Computes the standard deviation of this set.
     * 
     * @return the standard deviation.
     */
    public strictfp double getStandardDeviation() {
        return Math.sqrt(getVariance());
    }

    /**
     * Returns the textual representation of the state of this set.
     * 
     * @return the textual representation.
     */
    @Override
    public String toString() {
        return "[Size = " + size + ", average = " + getAverage() +
               ", s.d. = " + getStandardDeviation() + ", variance = " + 
                getVariance() + "]";
    }

    public static void main(String[] args) {
        StatisticsNumberSet set = new StatisticsNumberSet();

        set.add(1);
        set.add(1.0f);
        set.add((byte) 3);

        System.out.println(set);

        set.remove(1.0f);

        System.out.println(set);

        set.clear();

        System.out.println(set);
    }

    private void checkNumberIsFinite(double number) {
        if (Double.isNaN(number)) {
            throw new IllegalArgumentException("number is NaN");
        }

        if (Double.isInfinite(number)) {
            throw new IllegalArgumentException("number is +Inf or -Inf");
        }
    }
}

As always, any critique is much appreciated.