Slightly optimize next()

For ArrayBuffers and PriorityQueues, invoking isEmpty and size is slightly slower than invoking length.
This is because the former are overridden methods, and so the JVM needs to search through the virtual
methods table as Scala traits are compiled as Java interfaces.

This optimization is included as part of this PR because this patch adds emptiness checks on each key
comparison. This overheads associated are minor compared to disk read times, but potentially add up
as each call to next() involves many key comparisons.

A slight speed-up (<5%) has been observed in a local test that runs large shuffles.