@Override
  protected T computeNext() {
    if (delegate instanceof SkippingIterator<?>) {
      SkippingIterator<? extends T> skippingDelegate = (SkippingIterator<? extends T>) delegate;
      int toSkip = 0;
      while (random.nextDouble() >= samplingRate) {
        toSkip++;
      }
      // Really, would be nicer to select value from geometric distribution, for small values of samplingRate
      if (toSkip > 0) {
        skippingDelegate.skip(toSkip);
      }
      if (skippingDelegate.hasNext()) {
        return skippingDelegate.next();
      }
    } else {
      while (delegate.hasNext()) {
        T delegateNext = delegate.next();
        if (random.nextDouble() < samplingRate) {
          return delegateNext;
        }
      }
    }
    return endOfData();
  }