I have this data structure to which the user can add number or remove them, both in constant time. Also, there is a \$O(1)\$ operation for querying the standard deviation of the current contents of the structure:
StandardDeviationNumberSet.java
package net.coderodde.stat; import java.util.HashMap; import java.util.Map; public class StandardDeviationNumberSet { private double sum; private double squareSum; private int numberOfElements; private final Map<Double, Integer> countMap = new HashMap<>(); public void add(Number number) { double numberValue = number.doubleValue(); Integer count = countMap.get(numberValue); if (count != null) { countMap.put(numberValue, count + 1); } else { countMap.put(numberValue, 1); } sum += numberValue; squareSum += numberValue * numberValue; numberOfElements++; } public double remove(Number number) { double numberValue = number.doubleValue(); Integer count = countMap.get(numberValue); if (count != null) { if (count > 1) { countMap.put(numberValue, count - 1); } else { countMap.remove(numberValue); } sum -= numberValue; squareSum -= numberValue * numberValue; numberOfElements--; return numberValue; } else { return Double.NaN; } } public double getStandardDeviation() { checkSetHasAtleastTwoElements(); double step1 = squareSum - sum * sum / numberOfElements; double step2 = step1 / (numberOfElements - 1); return Math.sqrt(step2); } private void checkSetHasAtleastTwoElements() { if (numberOfElements < 2) { throw new IllegalStateException( "Computing the standard deviation requires at least two " + "elements."); } } public static void main(String[] args) { StandardDeviationNumberSet set = new StandardDeviationNumberSet(); set.add(1); set.add(1); set.add(3); System.out.println(set.getStandardDeviation()); set.remove(1); System.out.println(set.getStandardDeviation()); } }
As always, any critique is much appreciated.