@Override
  public int compare(Object s1, Object s2) {
    if (s1 instanceof Sketch) {
      if (s2 instanceof Sketch) {
        return SketchAggregatorFactory.COMPARATOR.compare((Sketch) s1, (Sketch) s2);
      } else {
        return -1;
      }
    }
    if (s1 instanceof Memory) {
      if (s2 instanceof Memory) {
        Memory s1Mem = (Memory) s1;
        Memory s2Mem = (Memory) s2;

        // We have two Ordered Compact sketches, so just compare their last entry if they have the
        // size.
        // This is to produce a deterministic ordering, though it might not match the actual
        // estimate
        // ordering, but that's ok because this comparator is only used by GenericIndexed
        int retVal = Longs.compare(s1Mem.getCapacity(), s2Mem.getCapacity());
        if (retVal == 0) {
          retVal =
              Longs.compare(
                  s1Mem.getLong(s1Mem.getCapacity() - 8), s2Mem.getLong(s2Mem.getCapacity() - 8));
        }

        return retVal;
      } else {
        return 1;
      }
    }
    throw new IAE("Unknwon class[%s], toString[%s]", s1.getClass(), s1);
  }
 @Override
 public byte[] toBytes(Object obj) {
   if (obj instanceof Sketch) {
     Sketch sketch = (Sketch) obj;
     if (sketch.isEmpty()) {
       return EMPTY_BYTES;
     }
     return sketch.toByteArray();
   } else if (obj instanceof Memory) {
     Memory mem = (Memory) obj;
     byte[] retVal = new byte[(int) mem.getCapacity()];
     mem.getByteArray(0, retVal, 0, (int) mem.getCapacity());
     return retVal;
   } else if (obj == null) {
     return EMPTY_BYTES;
   } else {
     throw new IAE("Unknown class[%s], toString[%s]", obj.getClass(), obj);
   }
 }