我想稍微扩展一下assylias所说的(他说得非常正确)。
首先,这些特性是以普通的int
形式实现的,它是二进制表示法。首先它是全零的,但是当你添加某个特性时,它的位通过OR
操作设置为one
,通过AND
操作移除。
您可以通过以下方式查看某个Spliterator属性设置其one
的位置:
System.out.println(Integer.toBinaryString(Spliterator.SIZED))
它将把从右边数第7个二进制位设置为1。所以当你检查时:
Spliterator<Integer> spliterator = Stream.of(8, 3, 5, 6, 7, 4).spliterator()
System.out.println((spliterator.characteristics() & Spliterator.SIZED) == Spliterator.SIZED)
你实际上是在检查是否设置了这个特定位。
第二点
有四个流特性是在你创建第一个流时设置的(不是两个)。 要么这本书已经过时了,要么你没有展示我们完整的例子:
Spliterator<Integer> spliterator = Stream.of(8, 3, 5, 6, 7, 4).spliterator();
System.out.println(Integer.bitCount(spliterator.characteristics()));
System.out.println(Integer.toBinaryString(spliterator.characteristics()));
这些被设置为 one
的比特位对应于 SIZED
, ORDERED
, IMMUTABLE
, SUBSIZED
。
你展示的其他一些显然也略微偏离了——你可以自己检查一下。
第三点
这些特性在流处理中非常重要。以下是一些例子:
long howMany = Stream.of(1, 2, 3).map(x -> {
System.out.println("mapping");
return x * 2;
}).count();
System.out.println(howMany);
在Java 9中,您将不会看到打印的映射(mapping)内容,因为您没有改变流(也没有清除SIZED特征),因此根本不需要评估映射(mapping)。
在Java 9中,由于您没有更改流(也没有清除SIZED特性),因此不需要甚至评估映射(mapping),所以您将无法看到该映射(mapping)打印。
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));
你可能会认为输出结果应该是false true
——毕竟我们加了一个limit
,但事实并非如此;结果是false false
:即使没有太多阻碍,也没有进行这样的优化。