How to correctly find the stream characteristics in Java-8?

java, java-8, java-stream

Solution

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.

Problem

While doing stream operations, during the intermediate/pipeline operations the streams would be created with different characteristics(e.g: SORTED/SIZED/DISTINCT/ORDERED) - Mastering Lambdas(Ch 6) ``` Stream.of(8,3,5,6,7,4) // ORDERED, SIZED .filter(i->i%2==0) // ORDERED .sorted() // ORDERED, SORTED .distinct() // DISTINCT, ORDERED, SORTED .map(i->i+1) // ORDERED .unordered(); // none ``` How do we find out the different characteristics of the stream as mentioned in the above snippet?

Original source