并行流上的迭代器()保证遇到顺序?

2022-09-04 21:35:48
Stream.of(a, b, c).parallel().map(Object::toString).iterator();

返回的迭代器是否保证按该顺序提供值 、 ?abc

我知道并保证集合具有正确顺序的值。另外,我不是在问如何从迭代器创建流。toArray()collect()


答案 1

这是规范中的疏忽。如果流具有定义的遭遇顺序,则其目的是其迭代器按遭遇顺序生成元素。如果流没有定义的遭遇顺序,迭代器当然会以某种顺序生成元素,但不会定义该顺序。

我已经提交了错误JDK-8194952来跟踪对规范的更改。

看起来其他人已经爬过足够的实现,以表明它确实会按遭遇顺序生成元素。此外,我们的流测试依赖于此属性。例如,收集器的测试断言列表中的元素以与从流的迭代器获取的顺序相同。因此,依赖此行为可能是安全的,即使它尚未正式指定(尚未)。toList


答案 2

Stream.of 方法用于从其他未关联的值创建流,返回顺序有序流。

返回一个顺序有序流,其元素为指定值。

根据java.util.stream的Javadocs副作用部分:

IntStream.range(0,5).parallel().map(x -> x*2).toArray()必须生产[0, 2, 4, 6, 8]

这意味着并保持流是否顺序/有序。parallel()map()

我已经将 创建的 实现追溯到一个名为 ReferencePipeline 的类。StreamStream.of

@Override
public final Iterator<P_OUT> iterator() {
    return Spliterators.iterator(spliterator());
}

该实现的方法服从于 Spliterator.iterator(),其代码通过简单地依赖于 's 方法来适应接口,并且不会更改任何流特征:iterator()IteratorSpliteratortryAdvance

public static<T> Iterator<T> iterator(Spliterator<? extends T> 
    spliterator) {
    Objects.requireNonNull(spliterator);
    class Adapter implements Iterator<T>, Consumer<T> {
        boolean valueReady = false;
        T nextElement;

        @Override
        public void accept(T t) {
            valueReady = true;
            nextElement = t;
        }

        @Override
        public boolean hasNext() {
            if (!valueReady)
                spliterator.tryAdvance(this);
            return valueReady;
        }

        @Override
        public T next() {
            if (!valueReady && !hasNext())
                throw new NoSuchElementException();
            else {
                valueReady = false;
                return nextElement;
            }
        }
    }

    return new Adapter();
}

总之,是的,顺序是有保证的,因为创建了一个“顺序有序流”,并且您在上面使用的任何操作都没有:,或更改特征。实际上,使用基础流来循环访问流元素。Stream.ofparallelmapiteratoriteratorSpliterator


推荐