views:

155

answers:

3

For logging purposes I want to collect the response times of an external system, and periodically fetch various statistics (such as min/max/stddev) of the response times. I'm looking for a pure in-memory solution.

What Java library can help me with this simple task?

I'm looking for an API that would ideally look something along the lines of:

StatisticsCollector s = new StatisticsCollector();
while (...) {
  double responseTime = ...;
  s.addObservation(responseTime);
}
double stddev = s.getStandardDeviation();
double mean = s.getMean();
+2  A: 

The DescriptiveStatistics class of the Apache Commons-Math project comes pretty close.

DescriptiveStatistics stat = new DescriptiveStatistics();
while (...) {
  double responseTime = ...;
  stat.addValue(responseTime);
}
double stddev = stat.getStandardDeviation();
double mean = stat.getMean() 
Joachim Sauer
Excellent answer! Exactly what I was looking for. Thanks!
knorv
A: 

You might be interested in Jsci http://jsci.sourceforge.net/

Specifically the sample statistics class:

http://jsci.sourceforge.net/api/JSci/maths/statistics/SampleStatistics.html

Sample API:

SampleStatistics()

int getCount()

double getMaximum()

double getMean()

double getMinimum()

double getVariance()

void update(double x)
Brian Gianforcaro
A: 

Or something like this:

package statistics;

import java.text.NumberFormat;
import java.text.DecimalFormat;

/**
 * Class for calculating means and standard deviations with a minimum of memory
 */
public class StatisticsUtils
{
   public static final String DEFAULT_FORMAT = "0.###";
   public static final NumberFormat FORMATTER = new DecimalFormat(DEFAULT_FORMAT);

   private long sum;
   private long squares;
   private long count;
   private long max;
   private long min;
   private long last;

   public static void main(String[] args)
   {
      StatisticsUtils stats = new StatisticsUtils();

      for (String arg : args)
      {
         stats.addValue(Long.valueOf(arg));
      }

      System.out.println(stats);
   }

   public StatisticsUtils()
   {
      reset();
   }

   public synchronized void addValue(long x)
   {
      sum += x;
      squares += x*x;
      min = ((x < min) ? x : min);
      max = ((x > max) ? x : max);
      last = x;
      ++count;

      // If the sum of squares exceeds Long.MAX_VALUE, this means the
      // value has overflowed; reset the state back to zero and start again.
      // All previous calculations are lost.  (Better as all doubles?)
      if (squares < 0L)
      {
         reset();
      }
   }

   public synchronized void reset()
   {
      sum = 0L;
      squares = 0L;
      count = 0L;
      max = Long.MIN_VALUE;
      min = Long.MAX_VALUE;
      last = 0L;
   }

   public synchronized double getMean()
   {
      double mean = 0.0;

      if (count > 0L)
      {
         mean = (double)sum/count;
      }

      return mean;
   }

   public synchronized double getStdDev()
   {
      double stdDev = 0.0;

      if (count > 1L)
      {
         stdDev = Math.sqrt((squares - (double)sum*sum/count)/(count-1));
      }

      return stdDev;
   }

   public synchronized long getCount()
   {
      return count;
   }

   public synchronized long getSum()
   {
      return sum;
   }

   public synchronized long getMax()
   {
      return max;
   }

   public synchronized long getMin()
   {
      return min;
   }

   public synchronized long getLast()
   {
      return last;
   }

   public String toString()
   {
      return "StatisticsUtils{" +
            "sum=" + sum + '\n' +
            ", min=" + min + '\n' +
            ", max=" + max + '\n' +
            ", last=" + last + '\n' +
            ", squares=" + squares + '\n' +
            ", count=" + count + '\n' +
            ", mean=" + FORMATTER.format(getMean()) + '\n' +
            ", dev=" + FORMATTER.format(getStdDev()) + '\n' +
            '}';
   }
}
duffymo