如何在Java-8中正确查找流特性?

16

在执行流操作时,在中间/管道操作期间,将创建具有不同特征(例如:SORTED/SIZED/DISTINCT/ORDERED)的流 - 《精通Lambda》(第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
我们如何找出上述片段中提到的流的不同特征?
2个回答

11

每个阶段都可以调用:

int c = stream.spliterator().characteristics();

然后将结果与Spliterator类中定义的常量进行比较。例如,检查流是否有序:


注:以下为机器翻译,仅供参考。

接下来,需要对结果与 Spliterator 类中定义的常量进行测试。例如,可以检查流是否有序:

boolean isOrdered = (c & Spliterator.ORDERED) == Spliterator.ORDERED;

或者您可以使用:

boolean isOrdered = stream.spliterator().hasCharacteristics(Spliterator.ORDERED);

4
@Eugene:你可以从Spliterator中重新创建流,在这里看,我猜这就是OP想要的... - Holger
2
@Holger 啊!从那个 Spliterator 返回一个流就有意义了...谢谢。对于达到 100k 表示真挚的祝贺。 - Eugene

10

我想稍微扩展一下assylias所说的(他说得非常正确)。

首先,这些特性是以普通的int形式实现的,它是二进制表示法。首先它是全零的,但是当你添加某个特性时,它的位通过OR操作设置为one,通过AND操作移除。

您可以通过以下方式查看某个Spliterator属性设置其one的位置:

System.out.println(Integer.toBinaryString(Spliterator.SIZED)); // 1000000

它将把从右边数第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())); // 4
System.out.println(Integer.toBinaryString(spliterator.characteristics()));// 100010001010000

这些被设置为 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); // 3
在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:即使没有太多阻碍,也没有进行这样的优化。


不,我已经给出了整个代码片段。可能是因为我使用的是过时版本的书。 - Chota Bheem
第三个例子(第二个片段),jdk9不会处理吗? - Chota Bheem

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接