How to correctly find the stream characteristics in Java-8?
I would like to slightly extend what assylias said (which is absolutely correct).
First, these characteristics are implemented as plain int
, it's binary representation. First it's all zeroes, but when you add a certain characteristic it's bit is set to one
via the OR
operation, removed via the AND
operation.
You can see where a certain Spliterator property sets its one
simply by doing this for example:
System.out.println(Integer.toBinaryString(Spliterator.SIZED)); // 1000000
It's setting the 7-th bit into one from the right. So when you check:
Spliterator<Integer> spliterator = Stream.of(8, 3, 5, 6, 7, 4).spliterator();
System.out.println((spliterator.characteristics() & Spliterator.SIZED) == Spliterator.SIZED);
You are actually checking if this particular bit is set.
Second
There are 4 stream characteristics that are set as the result of your first stream creation(and not two). Either the book is a bit outdated or you have not showed us the entire example:
Spliterator<Integer> spliterator = Stream.of(8, 3, 5, 6, 7, 4).spliterator();
System.out.println(Integer.bitCount(spliterator.characteristics())); // 4
System.out.println(Integer.toBinaryString(spliterator.characteristics()));// 100010001010000
These set bits (that are equal to one
) correspond to SIZED
, ORDERED
, IMMUTABLE
, SUBSIZED
.
The others that you have shown are obviously slightly off too - you can check those yourself.
Third
These characteristics are extremely important in stream processing. A few examples:
long howMany = Stream.of(1, 2, 3).map(x -> {
System.out.println("mapping");
return x * 2;
}).count();
System.out.println(howMany); // 3
In java-9 you will not see the mapping
printed, because you have not changed the stream (you have not cleared the SIZED
characteristic); thus no need to even evaluate the mapping at all.
Stream<Integer> unlimited = Stream.iterate(0, x -> x + 1);
System.out.println(unlimited.spliterator().hasCharacteristics(Spliterator.SIZED));
Stream<Integer> limited = unlimited.limit(3);
System.out.println(limited.spliterator().hasCharacteristics(Spliterator.SIZED));
You would think that the output should be false true
- we are adding a limit
after all, but no; the result is false false
: no such optimization is done, even if there is not much preventing it.
At each stage you can call:
int c = stream.spliterator().characteristics();
And then test the result against the constants defined in the Spliterator class. For example to see if the stream is ordered:
boolean isOrdered = (c & Spliterator.ORDERED) == Spliterator.ORDERED;
Alternatively you can use:
boolean isOrdered = stream.spliterator().hasCharacteristics(Spliterator.ORDERED);