All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.sf.jagg.HarmonicMeanAggregator Maven / Gradle / Ivy

Go to download

jAgg is a Java 5.0 API that supports “group by” operations on Lists of Java objects: aggregate operations such as count, sum, max, min, avg, and many more. It also allows custom aggregate operations.

The newest version!
package net.sf.jagg;

import net.sf.jagg.exception.ExpectedNumberException;
import net.sf.jagg.math.DoubleDouble;
import net.sf.jagg.model.WindowClause;

/**
 * This class represents the "harmonic mean" aggregator over numeric values.
 *
 * @author Randy Gettman
 * @since 0.1.0
 */
public class HarmonicMeanAggregator extends Aggregator implements AnalyticFunction
{
   private DoubleDouble mySum = new DoubleDouble();
   private long myCount;
   private long myNumZeroes;

   /**
    * Constructs an HarmonicMeanAggregator that operates on the specified
    * property.
    * @param property Calculate the harmonic mean of this property's values.
    */
   public HarmonicMeanAggregator(String property)
   {
      setProperty(property);
   }

   /**
    * Returns an uninitialized copy of this Aggregator object,
    * with the same property(ies) to analyze.
    * @return An uninitialized copy of this Aggregator object.
    */
   public HarmonicMeanAggregator replicate()
   {
      return new HarmonicMeanAggregator(getProperty());
   }
   
   /**
    * Initialize the sum and count to zero.
    */
   public void init()
   {
      mySum.reset();
      myCount = 0;
      myNumZeroes = 0;
   }

   /**
    * If not null, add the reciprocal of the property value to the sum and
    * count it.
    *
    * @param value The value to aggregate.
    */
   public void iterate(Object value)
   {
      if (value != null)
      {
         String property = getProperty();
         try
         {
            Number obj = (Number) getValueFromProperty(value, property);
            // Don't count nulls.
            if (obj != null)
            {
               myCount++;
               double d = obj.doubleValue();
               if (d == 0.0)
               {
                  myNumZeroes++;
               }
               else
               {
                  DoubleDouble temp = new DoubleDouble(1.0);
                  temp.divideSelfBy(obj.doubleValue());
                  mySum.addToSelf(temp);
               }
            }
         }
         catch (ClassCastException e)
         {
            throw new ExpectedNumberException("Property \"" + property +
               "\" must represent a Number.", e);
         }
      }
   }

   /**
    * If not null, subtract the reciprocal of the property value from the sum
    * and uncount it.
    *
    * @param value The value to remove.
    * @since 0.9.0
    */
   public void delete(Object value)
   {
      if (value != null)
      {
         String property = getProperty();
         try
         {
            Number obj = (Number) getValueFromProperty(value, property);
            // Don't count nulls.
            if (obj != null)
            {
               myCount--;
               double d = obj.doubleValue();
               if (d == 0.0)
               {
                  myNumZeroes--;
               }
               else
               {
                  DoubleDouble temp = new DoubleDouble(1.0);
                  temp.divideSelfBy(obj.doubleValue());
                  mySum.subtractFromSelf(temp);
               }
            }
         }
         catch (ClassCastException e)
         {
            throw new ExpectedNumberException("Property \"" + property +
               "\" must represent a Number.", e);
         }
      }
   }

   /**
    * The harmonic mean function can take a window clause.
    * @return true.
    * @since 0.9.0
    */
   public boolean takesWindowClause()
   {
      return true;
   }

   /**
    * The harmonic mean function doesn't supply its own window clause.
    * @return null
    * @since 0.9.0
    */
   public WindowClause getWindowClause()
   {
      return null;
   }

   /**
    * Merge the given Aggregator into this one by adding counts
    * and sums.
    *
    * @param agg The Aggregator to merge into this one.
    */
   public void merge(AggregateFunction agg)
   {
      if (agg != null && agg instanceof HarmonicMeanAggregator)
      {
         HarmonicMeanAggregator otherAgg = (HarmonicMeanAggregator) agg;
         mySum.addToSelf(otherAgg.mySum);
         myCount += otherAgg.myCount;
         myNumZeroes += otherAgg.myNumZeroes;
      }
   }

   /**
    * Return the harmonic mean by dividing the count by the sum.
    *
    * @return The harmonic mean as a Double.  Could return
    *    NaN if no values have been accumulated or if a zero
    *    exists in the values.
    */
   public Double terminate()
   {
      return terminateDoubleDouble().doubleValue();
   }

   /**
    * Return the result as a DoubleDouble.  This is used mainly
    * when other Aggregators that use this result must maintain a
    * high precision.
    * @return The harmonic mean as a DoubleDouble, or
    *    NaN if no values have been accumulated.
    * @since 0.4.0
    */
   public DoubleDouble terminateDoubleDouble()
   {
      if (myCount <= 0 || myNumZeroes > 0 || mySum.compareTo(DoubleDouble.ZERO) == 0)
         return new DoubleDouble(DoubleDouble.NaN);
      DoubleDouble result = new DoubleDouble(myCount);
      result.divideSelfBy(mySum);
      return result;
   }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy