@@ -215,82 +215,32 @@ public byte[] getBytes() throws IOException
215
215
}
216
216
217
217
@ Override
218
- public ICardinality merge (ICardinality ... estimators )
218
+ public ICardinality merge (ICardinality ... estimators ) throws CardinalityMergeException
219
219
{
220
- return HyperLogLog .mergeEstimators (prepMerge (estimators ));
221
- }
222
-
223
- protected HyperLogLog [] prepMerge (ICardinality ... estimators )
224
- {
225
- int numEstimators = (estimators == null ) ? 0 : estimators .length ;
226
- HyperLogLog [] lls = new HyperLogLog [numEstimators + 1 ];
227
- if (numEstimators > 0 )
220
+ if (estimators == null || estimators .length == 0 )
228
221
{
229
- for (int i = 0 ; i < numEstimators ; i ++)
230
- {
231
- if (estimators [i ] instanceof HyperLogLog )
232
- {
233
- lls [i ] = (HyperLogLog ) estimators [i ];
234
- }
235
- else
236
- {
237
- throw new RuntimeException ("Unable to merge HyperLogLog with " + estimators [i ].getClass ().getName ());
238
- }
239
- }
222
+ return this ;
240
223
}
241
- lls [numEstimators ] = this ;
242
- return lls ;
243
- }
244
-
245
- /**
246
- * @param estimators
247
- * @return null if no estimators are provided
248
- */
249
- protected static RegisterSet mergeRegisters (HyperLogLog ... estimators )
250
- {
251
- RegisterSet mergedSet = null ;
252
- int numEstimators = (estimators == null ) ? 0 : estimators .length ;
253
- if (numEstimators > 0 )
224
+ RegisterSet mergedSet ;
225
+ int size = this .sizeof ();
226
+ mergedSet = new RegisterSet ((int ) Math .pow (2 , this .log2m ), this .registerSet .bits ());
227
+ for (ICardinality estimator : estimators )
254
228
{
255
- int size = estimators [0 ].sizeof ();
256
- mergedSet = new RegisterSet ((int ) Math .pow (2 , estimators [0 ].log2m ));
257
-
258
- for (int e = 0 ; e < numEstimators ; e ++)
229
+ if (!(estimator instanceof HyperLogLog ))
259
230
{
260
- if (estimators [e ].sizeof () != size )
261
- {
262
- throw new RuntimeException ("Cannot merge estimators of different sizes" );
263
- }
264
- HyperLogLog estimator = estimators [e ];
265
- for (int b = 0 ; b < mergedSet .count ; b ++)
266
- {
267
- if (estimator .registerSet .get (b ) > mergedSet .get (b ))
268
- {
269
- mergedSet .set (b , estimator .registerSet .get (b ));
270
- }
271
- }
231
+ throw new HyperLogLogMergeException ("Cannot merge estimators of different class" );
232
+ }
233
+ if (estimator .sizeof () != size )
234
+ {
235
+ throw new HyperLogLogMergeException ("Cannot merge estimators of different sizes" );
236
+ }
237
+ HyperLogLog hll = (HyperLogLog ) estimator ;
238
+ for (int b = 0 ; b < mergedSet .count ; b ++)
239
+ {
240
+ mergedSet .set (b , Math .max (mergedSet .get (b ), hll .registerSet .get (b )));
272
241
}
273
242
}
274
- return mergedSet ;
275
- }
276
-
277
- /**
278
- * Merges estimators to produce an estimator for their combined streams
279
- *
280
- * @param estimators
281
- * @return merged estimator or null if no estimators were provided
282
- */
283
- public static HyperLogLog mergeEstimators (HyperLogLog ... estimators )
284
- {
285
- HyperLogLog merged = null ;
286
-
287
- RegisterSet mergedSet = mergeRegisters (estimators );
288
- if (mergedSet != null )
289
- {
290
- merged = new HyperLogLog (estimators [0 ].log2m , mergedSet );
291
- }
292
-
293
- return merged ;
243
+ return new HyperLogLog (this .log2m , mergedSet );
294
244
}
295
245
296
246
public static int [] getBits (byte [] mBytes ) throws IOException
@@ -339,4 +289,13 @@ public static HyperLogLog build(byte[] bytes) throws IOException
339
289
return new HyperLogLog (log2m , new RegisterSet ((int ) Math .pow (2 , log2m ), getBits (longArrayBytes )));
340
290
}
341
291
}
292
+
293
+ @ SuppressWarnings ("serial" )
294
+ protected static class HyperLogLogMergeException extends CardinalityMergeException
295
+ {
296
+ public HyperLogLogMergeException (String message )
297
+ {
298
+ super (message );
299
+ }
300
+ }
342
301
}
0 commit comments