HyperLogLog implements IRichCardinality { @Override public IRichCardinality merge(IRichCardinality... estimators) throws CardinalityMergeException { HyperLogLog merged = new HyperLogLog(log2m); merged.addAll(this); if (estimators == null) { return merged; } for (IRichCardinality estimator : estimators) { if (!(estimator instanceof HyperLogLog)) { throw new HyperLogLogMergeException("Cannot merge estimators of different class"); } HyperLogLog hll = (HyperLogLog) estimator; merged.addAll(hll); } return merged; } HyperLogLog(double rsd);  HyperLogLog(int log2m);  HyperLogLog(int log2m, RegisterSet registerSet); @Override boolean offerHashed(long hashedValue); @Override boolean offerHashed(int hashedValue); @Override boolean offer(Object o); @Override long cardinality(); @Override int sizeof(); @Override byte[] getBytes(); void addAll(HyperLogLog other); @Override IRichCardinality merge(IRichCardinality... estimators);  }
@Test public void testMerge() throws CardinalityMergeException { int numToMerge = 5; int bits = 16; int cardinality = 1000000; HyperLogLog[] hyperLogLogs = new HyperLogLog[numToMerge]; HyperLogLog baseline = new HyperLogLog(bits); for (int i = 0; i < numToMerge; i++) { hyperLogLogs[i] = new HyperLogLog(bits); for (int j = 0; j < cardinality; j++) { double val = Math.random(); hyperLogLogs[i].offer(val); baseline.offer(val); } } long expectedCardinality = numToMerge * cardinality; HyperLogLog hll = hyperLogLogs[0]; hyperLogLogs = Arrays.asList(hyperLogLogs).subList(1, hyperLogLogs.length).toArray(new HyperLogLog[0]); long mergedEstimate = hll.merge(hyperLogLogs).cardinality(); long baselineEstimate = baseline.cardinality(); double se = expectedCardinality * (1.04 / Math.sqrt(Math.pow(2, bits))); System.out.println("Baseline estimate: " + baselineEstimate); System.out.println("Expect estimate: " + mergedEstimate + " is between " + (expectedCardinality - (3 * se)) + " and " + (expectedCardinality + (3 * se))); assertTrue(mergedEstimate >= expectedCardinality - (3 * se)); assertTrue(mergedEstimate <= expectedCardinality + (3 * se)); assertEquals(mergedEstimate, baselineEstimate); }