# The Java Embedded Aggregator Class ApproxDistinctCount Aggregate

ApproxDistinctCountAggregate implements the "approximate distinct count" aggregation. (Note that this is not a precise result.)

### For an overview see page Java Aggregator Class

### Class Definition

        public static class ApproxDistinctCountAggregate implements Aggregate
        {
            static final int HASH_BITS = 25;
            static final int N_HASHES = 1 << (32 - HASH_BITS);

            public void initialize(Object val)
            {
                accumulate(val);
            }

            public void accumulate(Object val)
            {
                int h = val.hashCode();
                int j = h >>> HASH_BITS;
                int zeroBits = 1;
                while ((h & 1) == 0 && zeroBits <= HASH_BITS)
                 {
                    h >>>= 1;
                    zeroBits += 1;
                }
                if (maxZeroBits[j] < zeroBits)
                {
                    maxZeroBits[j] = zeroBits;
                }
            }

            public Object result()
            {
                final int m = N_HASHES;
                final double alpha_m = 0.7213 / (1 + 1.079 / (double)m);
                final double pow_2_32 = 0xffffffff;
                double E, c = 0;
                int i;
                for (i = 0; i < m; i++)
                {
                    c += 1 / Math.pow(2., (double)maxZeroBits[i]);
                }
                E = alpha_m * m * m / c;

                if (E <= (5 / 2. * m))
                {
                    double V = 0;
                    for (i = 0; i < m; i++)
                    {
                        if (maxZeroBits[i] == 0)
                        {
                            V += 1;
                        }
                    }
                    if (V > 0)
                    {
                        E = m * Math.log(m / V);
                    }
                }
                else if (E > (1 / 30. * pow_2_32))
                {
                    E = -pow_2_32 * Math.log(1 - E / pow_2_32);
                }
                return new Long((long)E);
            }

            public void merge(Aggregate other)
            {
                int[] otherMaxZeroBits = ((ApproxDistinctCountAggregate)other).maxZeroBits;
                for (int i = 0; i < N_HASHES; i++)
                {
                    if (maxZeroBits[i] < otherMaxZeroBits[i])
                    {
                        maxZeroBits[i] = otherMaxZeroBits[i];
                    }
                }
            }

            int[] maxZeroBits = new int[N_HASHES];
        }