[SPARK-3250] Implement Gap Sampling optimization for random sampling

More efficient sampling, based on Gap Sampling optimization:
http://erikerlandson.github.io/blog/2014/09/11/faster-random-samples-with-gap-sampling/

I did it this way because `data.hasNext` will be true until the very end, when `rep > 0` might come into play, so checking `hasNext` will short-circuit first.   `rep` will be zero more often than not for many sampling fractions, so it would frequently fall through to the `hasNext` check anyway