Java 深刻理解分配器的特性

Java 深刻理解分配器的特性,java,java-8,java-stream,spliterator,Java,Java 8,Java Stream,Spliterator,为了深入理解java流和拆分器,我有一些关于拆分器特性的微妙问题: Q1:Stream.empty()vsStream.of()(Stream.of()不带参数) Stream.empty():子项,大小 Stream.of() 为什么Stream.empty()?请注意,它与Stream.concat()结合使用时会产生影响(特别是没有排序的)。我想说,Stream.empty()不仅应该具有不可变的和有序的属性,还应该具有独特的和非空的属性。而且,只有一个参数具有DISTICT,它才有意

为了深入理解java流和拆分器,我有一些关于拆分器特性的微妙问题

Q1:
Stream.empty()
vs
Stream.of()
(Stream.of()不带参数)

  • Stream.empty()
    :子项,大小
  • Stream.of()
为什么
Stream.empty()?请注意,它与Stream.concat()结合使用时会产生影响(特别是没有排序的
)。我想说,
Stream.empty()
不仅应该具有不可变的和有序的属性,还应该具有独特的和非空的属性。而且,只有一个参数具有DISTICT,它才有意义
Stream.of()

Q2:
LongStream.of()
不具有非空值

刚才注意到NONNULL在
LongStream.of中不可用。
NONNULL
不是所有
LongStream
s、
IntStream
s和
DoubleStream
s的主要特征吗

Q3:
LongStream.range(,)
vs
LongStream.range(,).boxed()

  • 长范围。范围(,)
    :子化,不可变,非空,大小,顺序,排序,不同
  • LongStream.range(,).boxed()
    :子项、大小、顺序
为什么
.boxed()
会丢失所有这些特性?它不应该丢失任何东西

我知道
.mapToObj()
可能会丢失非null、不可变和DISTICT,但是
.boxed()
。。。没有道理

Q4:
.peek()
将丢失不可变和非空值

LongStream.of(1)
:子化、不可变、非空、大小。。。
LongStream.of(1).peek()
:子化、大小化

为什么
.peek()
会丢失这些特性
.peek
不应该真的丢失任何东西

Q5:
.skip()
.limit()
丢失子项、不可变、非空、大小

请注意,这些操作将丢失子化的、不可变的、非空的、大小为的。为什么?如果尺寸可用,那么也很容易计算最终尺寸

Q6:
.filter()
丢失不可变的非空值

请注意,此操作也会丢失子化、不可变、非空、大小。失去补贴和规模是有道理的,但其他两个没有道理。为什么?



如果有人对拆分器有深入的了解,能够提供一些清晰的信息,我将不胜感激。谢谢。

我必须承认,当我第一次试图找出这些特性的实际含义时,我也遇到了困难,我觉得它们的含义在Java 8的实现阶段没有得到明确的解决,因此使用时不一致

考虑:

表示元素源在结构上无法修改的特征值;也就是说,不能添加、替换或删除元素,因此在遍历过程中不会发生此类更改

在这个列表中看到“替换”是很奇怪的,当谈到
列表
或数组时,它通常不被视为结构修改,因此,流和拆分器工厂接受数组(未克隆)报告
不可变
,如
LongStream.of(…)
Arrays.spliterator(长[])

如果我们更宽泛地解释为“只要客户不可见”,与并发
没有显著差异,因为在这两种情况下,有些元素将报告给客户端,而无法识别它们是在遍历过程中添加的还是由于删除而未报告的,因为无法回放拆分器并进行比较

本规范继续说明:

对于不报告
不可变
并发
的拆分器,在遍历过程中检测到的结构干扰方面,需要有一个文档化的策略(例如抛出
并发修改异常

这是唯一相关的事情,
IMMUTABLE
CONCURRENT
报告的拆分器保证不会抛出
ConcurrentModificationException
。当然,
CONCURRENT
在语义上排除了
大小的
,但这对客户端代码没有影响

事实上,这些特性并没有用于流API中的任何内容,因此,不一致地使用它们永远不会引起注意

这也是为什么每个中间操作都具有清除
并发
不可变
非空
特征的效果的原因:流实现不使用这些特征,并且表示流状态的内部类不维护它们


类似地,
NONNULL
在任何地方都没有使用,因此它对于某些流没有任何影响。我可以跟踪(…)的
LongStream.of
问题,直到
数组的内部使用。拆分器(long[],int,int)
委托给
:

返回的拆分器始终报告特性
大小
子项
。调用者可能会提供其他特性供拆分器报告。(例如,如果已知数组不会被进一步修改,则指定
不可变
;如果数组数据被认为具有遭遇顺序,则指定
有序
)。方法
数组.spliterator(long[],int,int)通常可以使用
,它返回一个拆分器,报告
大小
子项
不可变
有序

附注(aga)