3

哪些流操作使用CONCURRENT,IMMUTABLENONNULLSpliterator 特征?他们每个人如何帮助这些操作?


我不是在问那些标志是什么,这可以在文档中很容易地找到。我在问哪些操作使用它们以及如何使用它们。

4

3 回答 3

3

首先,您应该明确区分您在Spliterator这里询问的特征,这些特征取决于 Stream 的来源;因为还有 ( CONCURRENT,UNORDEREDIDENTITY_FINISH例如Collectors)。

有评论StreamOpFlag说:

// The following Spliterator characteristics are not currently used but a
// gap in the bit set is deliberately retained to enable corresponding
// stream flags if//when required without modification to other flag values.
//
// 4, 0x00000100 NONNULL(4, ...
// 5, 0x00000400 IMMUTABLE(5, ...
// 6, 0x00001000 CONCURRENT(6, ...
// 7, 0x00004000 SUBSIZED(7, ...

据我了解,这些不是与 Spliterator 的直接一对一映射,但仍然没有使用它们。

目前 (我已经搜索了 jdk-8 和 9 来源),两者都没有被利用——但仍然被 Spliterators 的一些实现报告(例如Arrays报告IMMUTABLEConcurrentHashMap报告)。NONNULL

另一方面,这些标志可以在将来使用 - 如果您知道源不能包含 null 元素 ( NONNULL),显然您可以跳过一些 null 检查或使用 null 定义某些状态。我想不出CONCURRENTor的任何例子IMMUTABLE,但可能有这样的例子。

例如,在一个UNORDEREDCONCURRENT收集器(!=Spliterator属性)的当前实现下,combiner当你这样做时不会调用toConcurrentMap。例如:

Set.of("one", "two", "das", "dasda")
            .stream()
            .parallel()
            .collect(Collectors.toConcurrentMap(Function.identity(), String::length));

不会调用combiner- 因为没有必要。

可以针对您提到的 3 个特征中的任何一个进行此类优化。例如,您可以阅读this where StreamOpFlag.ORDEREDhas changed the result findFirstin java 8 vs java 9

于 2017-08-16T13:19:04.027 回答
1

在 Java 8 中,流操作不使用这 3 个特性。这可以通过在 Java 源代码中搜索这些常量来检查。

但是,CONCURRENT当您编写自己的集合时,该特性可能会影响并行流的行为。如果您Spliterator从集合创建一个而不报告CONCURRENT特征,那么拆分器将另外具有SIZEDSUBSIZED特征:

Collection<Integer> col = ...
Spliterator<Integer> s = Spliterators.spliterator(col, 0);

System.out.println(s.hasCharacteristics(Spliterator.SIZED)); // Prints true
System.out.println(s.hasCharacteristics(Spliterator.SUBSIZED)); // Prints true

但是,如果您报告CONCURRENT特征,则拆分器SIZED不再是:

Collection<Integer> col = ...
Spliterator<Integer> s = Spliterators.spliterator(col, Spliterator.CONCURRENT);

System.out.println(s.hasCharacteristics(Spliterator.SIZED)); // Prints false
System.out.println(s.hasCharacteristics(Spliterator.SUBSIZED)); // Prints false

未并行化SIZEDSUBSIZED并行性较差的拆分器,因此当您编写自己的并发集合时,最好编写自定义拆分器而不依赖默认拆分器实现。

于 2017-08-16T11:05:30.380 回答
1

人们说IMMUTABLE没有使用,但事实证明,Stream#iterate报告IMMUTABLE

jshell> Stream.iterate(0, i -> i + 1).spliterator().characteristics()
$1 ==> 1040

1040 是IMMUTABLE | ORDERED,但它看起来像任何操作都会丢弃IMMUTABLE(使用map, filter, flatMap, limit, skip; 在 Java 16 上测试)
IntStream#iterateLongStream#iterate并且DoubleStream#iterate报告NONNULL也是如此,但下一个操作也会丢弃。

于 2021-08-26T14:36:35.490 回答