I came to know while studying that Parallelism
is a main advantage of Spliterator
.
This may be a basic question but can anyone explain me the main differences between Iterator
and Spliterator
and give some examples?
I came to know while studying that Parallelism
is a main advantage of Spliterator
.
This may be a basic question but can anyone explain me the main differences between Iterator
and Spliterator
and give some examples?
An
Iterator
is a simple representation of a series of elements that can be iterated over.eg:
A
Spliterator
can be used to split given element set into multiple sets so that we can perform some kind of operations/calculations on each set in different threads independently, possibly taking advantage of parallelism. It is designed as a parallel analogue of Iterator. Other than collections, the source of elements covered by a Spliterator could be, for example, an array, an IO channel, or a generator function.There are 2 main methods in the
Spliterator
interface.- tryAdvance() and forEachRemaining()
With tryAdvance(), we can traverse underlying elements one by one (just like Iterator.next()). If a remaining element exists, this method performs the consumer action on it, returning true; else returns false.
For sequential bulk traversal we can use forEachRemaining():
Output:
- Spliterator trySplit()
Splits this spliterator into two and returns the new one:
Output:
An ideal trySplit method should divide its elements exactly in half, allowing balanced parallel computation.
The splitting process is termed as 'partitioning' or 'decomposition' as well.
The names are pretty much self-explanatory, to me.
Spliterator
== Splittable Iterator : it can split some source and it can iterate it too. It's sort of has the same functionality like anIterator
, but with the extra thing that it can potentially split into multiple pieces, this is whattrySplit
is for. Splitting is needed for parallel processing.An
Iterator
has always an unknown size, you can traverse elements only viahasNext/next
; aSpliterator
can provide the size (thus improving other operations too internally); either an exact one viagetExactSizeIfKnown
or a approximate viaestimateSize
.On the other hand,
tryAdvance
is whathasNext/next
is from anIterator
, but it's a single method, much easier to reason about IMO. Related to this isforEachRemaining
which in the default implementation delegates totryAdvance
, but it does not have to be like this always. (seeArrayList
for example)A Spliterator is also a "smarter" Iterator, via it's internal properties like
DISTINCT
orSORTED
, etc (which you need to provide correctly when implementing your ownSpliterator
). These flags are used internally to disable unnecessary operations, also called optimizations, like this one for example:Because size does not change in case of the stream, the
map
can be skipped entirely, since all we do is counting.You can create a Spliterator around an Iterator if you would need to, via: