为了尝试深入了解Java流和分隔符,我对分隔符特性有一些微妙的问题:
Q1:Stream.empty()
与Stream.of()
(不带args的Stream.of())
Stream.empty()
:SUBSIZED,SIZED Stream.of()
:SUBSIZED, IMMUTABLE ,SIZED, ORDERED 为什么
Stream.empty()
不具有Stream.of()
的相同特征?请注意,与Stream.concat()结合使用时会产生影响(特别是没有ORDERED
)。我要说的是,Stream.empty()
不仅应具有IMMUTABLE和ORDERED,而且还应具有DISTINCT和NONNULL。另外,只有一个具有DISTICT的参数才有意义Stream.of()
。Q2:
LongStream.of()
没有NONNULL 只是注意到NONt在
LongStream.of
中不可用。NONNULL
不是所有LongStream
,IntStream
和DoubleStream
的主要特征吗?第3季度:
LongStream.range(,)
与LongStream.range(,).boxed()
LongRange.range(,)
:SUBSIZED, IMMUTABLE,NONNULL ,SIZED,ORDERED, SORTED,DISTINCT LongStream.range(,).boxed()
:SUBSIZED,SIZED,ORDERED 为什么
.boxed()
失去所有这些特征?它不应该丢失任何东西。我知道
.mapToObj()
可能会丢失NONNULL,IMMUTABLE和DISTICT,但是.boxed()
...没有任何意义。Q4:
.peek()
丢失IMMUTABLE和NONNULL LongStream.of(1)
:SUBSIZED,IMMUTABLE,NONNULL,SIZED,...LongStream.of(1).peek()
:SUBSIZED,SIZED,...为什么
.peek()
失去这些特征? .peek
应该不会丢失任何内容。Q5:
.skip()
,.limit()
失去SUBSIZED,IMMUTABLE,NONNULL,SIZED 只需注意,这些操作将丢失SUBSIZED,IMMUTABLE,NONNULL,SIZED。为什么?如果有可用的尺寸,那么也很容易计算出最终尺寸。
Q6:
.filter()
丢失IMMUTABLE,NONNULL 只需注意,此操作也将丢失,包括:SUBSIZED,IMMUTABLE,NONNULL,SIZED。失去SUBSIZED和SIZED是有意义的,但是其他两个则没有意义。为什么?
如果有人对分离器有深入的了解,可以使您感到清楚,我将不胜感激。谢谢。
最佳答案
我不得不承认,当我第一次尝试找出特征的实际含义时,我也遇到了困难,并且感觉到它们的含义在Java 8的实现阶段没有明确地确定,并且由于这个原因而被不一致地使用。
考虑 Spliterator.IMMUTABLE
:
看到此列表中的“已替换”很奇怪,当谈到List
或数组时,通常不将其视为结构修改,因此,流和分离器工厂接受数组(未克隆)报告IMMUTABLE
,例如LongStream.of(…)
或Arrays.spliterator(long[])
。
如果我们将其更宽泛地解释为“只要客户端无法观察到”,则CONCURRENT
并没有显着差异,因为在两种情况下,有些元素都会报告给客户端,而无法识别在遍历过程中是否添加了它们是否有些由于删除而未报告,因为无法倒带分隔器并进行比较。
规范继续:
这是唯一相关的事情,可以保证报告IMMUTABLE
或CONCURRENT
的分隔符永远不会抛出ConcurrentModificationException
。当然,CONCURRENT
在语义上排除了SIZED
,但这对客户端代码没有影响。
实际上,这些特性在Stream API中并没有用于任何东西,因此,不一致地使用它们永远不会在某处引起注意。
这也解释了为什么每个中间操作都具有清除CONCURRENT
,IMMUTABLE
和NONNULL
特性的作用:Stream实现不使用它们,并且表示流状态的内部类不维护它们。
同样,NONNULL
不会在任何地方使用,因此某些流不存在就没有影响。我可以跟踪LongStream.of(…)
问题,直到Arrays.spliterator(long[], int, int)
的内部使用(委托(delegate)给
Spliterators.spliterator(long[] array, int fromIndex, int toIndex, int additionalCharacteristics)
:
再次请注意IMMUTABLE
特性的用法不一致。再次被视为必须保证不进行任何修改,同时Arrays.spliterator
以及Arrays.stream
和LongStream.of(…)
甚至即使通过规范也将报告IMMUTABLE
特性,而不能保证调用者不会修改其数组。除非我们考虑将元素设置为非结构性修改,否则整个区别又变得毫无意义,因为数组无法进行结构性修改。
并且它明确规定没有NONNULL
特征。很明显,原始值不能是null
,并且Spliterator.Abstract<Primitive>Spliterator
类总是注入(inject)NONNULL
特征,但Spliterators.spliterator(long[],int,int,int)
返回的分隔符不会继承自Spliterator.AbstractLongSpliterator
。
不好的是,这不能在不更改规格的情况下得到解决,而好的事情是,它不会有任何后果。
因此,如果我们忽略CONCURRENT
,IMMUTABLE
或NONNULL
的任何问题,而没有任何后果,那么我们就有SIZED
和skip
和limit
。这是一个众所周知的问题,是Stream API已实现skip
和limit
的结果。其他实现是可以想象的。这也适用于无限流与limit
的组合,该组合应具有可预测的大小,但考虑到当前的实现,则没有。
结合Stream.concat(…)
和Stream.empty()
。合理的认为,空流不会对结果顺序施加约束。但是Stream.concat(…)
在只有一个输入没有订单的情况下释放订单的行为值得怀疑。请注意,在订购时过于激进并不是什么新鲜事,请参阅this Q&A来了解首先被认为是有意的行为,但后来在Java 8 update 60中已得到修复。也许在这个时间点上也应该讨论Stream.concat
。 ….boxed()
的行为很容易解释。当像.mapToObj(Long::valueOf)
这样天真地实现它时,它将简单地失去所有知识,因为mapToObj
不能假设结果仍然是排序或不同的。但这已在Java 9中修复。那里LongStream.range(0,10).boxed()
具有SUBSIZED|SIZED|ORDERED|SORTED|DISTINCT
特性,并维护与实现相关的所有特性。
关于java - 深入了解分离器特性,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/46644595/