标签: spliterator

不可分裂的分裂器

我试图了解它是如何Spliterator工作的,以及如何设计分裂器.我认识到这trySplit()可能是更重要的方法之一Spliterator,但是当我看到一些第三方Spliterator实现时,有时我会看到他们的分裂器trySplit()无条件地返回null .

问题:

  1. 普通迭代器和Spliterator无条件返回null 之间有区别吗?看起来这样的分裂者似乎击败了分裂.
  2. 当然,有一些合法的分裂器用例有条件地返回null trySplit(),但是有一个无条件返回null的分裂器的合法用例吗?

java java-8 spliterator

11
推荐指数
1
解决办法
893
查看次数

您可以重新平衡大小未知的不平衡分离器吗?

我想使用a Stream并行处理未知数量(文件数量在预先未知的情况下)的异类远程存储JSON文件集。文件的大小可以相差很大,从每个文件1个JSON记录到其他文件中的100,000个记录。甲JSON记录在这种情况下是指表示为文件中的一条线的自包含JSON对象。

我真的很想为此使用Streams,所以我实现了这一点Spliterator

public abstract class JsonStreamSpliterator<METADATA, RECORD> extends AbstractSpliterator<RECORD> {

    abstract protected JsonStreamSupport<METADATA> openInputStream(String path);

    abstract protected RECORD parse(METADATA metadata, Map<String, Object> json);

    private static final int ADDITIONAL_CHARACTERISTICS = Spliterator.IMMUTABLE | Spliterator.DISTINCT | Spliterator.NONNULL;
    private static final int MAX_BUFFER = 100;
    private final Iterator<String> paths;
    private JsonStreamSupport<METADATA> reader = null;

    public JsonStreamSpliterator(Iterator<String> paths) {
        this(Long.MAX_VALUE, ADDITIONAL_CHARACTERISTICS, paths);
    }

    private JsonStreamSpliterator(long est, int additionalCharacteristics, Iterator<String> paths) {
        super(est, additionalCharacteristics);
        this.paths = paths;
    }

    private JsonStreamSpliterator(long …
Run Code Online (Sandbox Code Playgroud)

java java-8 java-stream spliterator

11
推荐指数
1
解决办法
193
查看次数

Stream.spliterator对并行流的奇怪行为

我正在使用流分裂器直接用于我正在编写的库中的低级操作.最近,当我使用流分裂器和交错tryAdvance/trySplit调用时,我发现了非常奇怪的行为.这是一个简单的代码,演示了这个问题:

import java.util.Arrays;
import java.util.Spliterator;

public class SpliteratorBug {
    public static void main(String[] args) {
        Integer[][] input = { { 1 }, { 2, 3 }, { 4, 5, 6 }, { 7, 8 }, { 9 } };
        Spliterator<Integer> spliterator = Arrays.stream(input).parallel()
                .flatMap(Arrays::stream).spliterator();
        spliterator.trySplit();
        spliterator.tryAdvance(s -> {});
        spliterator.trySplit();
        spliterator.forEachRemaining(System.out::println);
    }
}
Run Code Online (Sandbox Code Playgroud)

输出是

5
6
9
Run Code Online (Sandbox Code Playgroud)

正如你所看到的,后平映射我应该得到连续编号的有序流19.我将分裂器分开一次,所以它应该跳到一些中间位置.接下来我从中消耗一个元素并将其拆分一次.之后我打印所有剩余的元素.我希望我将从流尾部有几个连续的元素(可能是零元素,它也会很好).然而我所得到的是56,然后突然跳出来9.

我知道目前在JDK分裂器中并没有这样使用:它们总是在遍历之前分裂.但是官方文档没有明确禁止调用trySplittryAdvance.

当我使用直接从集合,数组,生成的源等创建的spliterator时,从未观察到这个问题.只有当spliterator是从具有中间体的并行流创建时才会观察到flatMap.

所以问题是:我是否遇到了这个错误,或者明确禁止某个地方以这种方式使用分裂器?

java java-8 java-stream spliterator

10
推荐指数
2
解决办法
589
查看次数

在顺序Spliterator上的estimateSize()

我正在实现一个Spliterator通过trySplit()返回明确限制并行化的方法null.实施estimateSize()是否会为此分裂器生成的流提供任何性能改进?或者估计的大小仅对并行化有用?

编辑:澄清一下,我特别询问估计的大小.换句话说,我的分裂者没有这个SIZED特征.

java java-8 java-stream spliterator

8
推荐指数
1
解决办法
446
查看次数

Spliterator与Stream.Builder

我读了一些关于如何创建有限的问题Stream( 在Java中有限生成的流 - 如何创建一个?,流如何停止?).

答案建议实施一个Spliterator.在Spliterator将实现逻辑如何和元件,以提供为下一个(tryAdvance).但也有其他两个非默认的方法trySplitestimateSize()我将不得不执行.

JavaDoc Spliterator说:

用于遍历和分区源元素的对象.a覆盖的元素源Spliterator可以是例如阵列,a Collection,IO通道或生成器函数.... Spliterator除了顺序遍历之外,API还支持有效的并行遍历,支持分解以及单元素迭代....

另一方面,我可以实现逻辑如何前进到a周围的下一个元素Stream.Builder并绕过a Spliterator.在每次前进时我都会打电话accept或者add最后打电话build.所以它看起来很简单.

JavaDoc说什么?

一个可变的建设者Stream.这允许Stream 通过单独生成元素并将它们添加到Builder (无需使用ArrayList作为临时缓冲区的复制开销)来创建.

使用StreamSupport.stream我可以用a Spliterator来获取Stream.并且Builder还将提供一个Stream.

什么时候应该/我可以使用Stream.Builder
只有当a Spliterator不会更高效时(例如因为无法对源进行分区并且无法估计其大小)?

java builder java-8 java-stream spliterator

7
推荐指数
1
解决办法
408
查看次数

从排序的流中获取spliterator会引发异常

根据文件Spliterator#getComparator,它说

如果此Spliterator的源是SORTEDa Comparator,则返回 Comparator.如果源是SORTED自然顺序,则返回null.否则,如果源不是SORTED,则抛出IllegalStateException.

实施要求:

始终抛出默认实现IllegalStateException.

返回:a Comparator,或者null元素是按自然顺序排序的.

抛出:IllegalStateException- 如果分裂器没有报告特征SORTED.

所以在运行这段代码时

Spliterator<Integer> spliterator = Stream.of(1, 2, 3).sorted().spliterator();

System.out.println((spliterator.characteristics() & Spliterator.SORTED) == Spliterator.SORTED);
System.out.println(spliterator.getComparator());
Run Code Online (Sandbox Code Playgroud)

我明白了:

true
null
Run Code Online (Sandbox Code Playgroud)

到现在为止还挺好.现在这样做:

Spliterator<Integer> spliterator = Stream.of(1, 2, 3).sorted(Comparator.naturalOrder()).spliterator();

System.out.println((spliterator.characteristics() & Spliterator.SORTED) == Spliterator.SORTED);
System.out.println(spliterator.getComparator());
Run Code Online (Sandbox Code Playgroud)

它输出false并抛出异常:

Exception in thread "main" java.lang.IllegalStateException
    at java.util.stream.StreamSpliterators$AbstractWrappingSpliterator.getComparator(StreamSpliterators.java:259)
    at SpliteratorTest.main(SpliteratorTest.java:10)
Run Code Online (Sandbox Code Playgroud)

为什么它输出false并抛出异常?

根据文件,它不应该给我Comparator提供给我的sorted()吗?

(这也发生在reverseOrder() …

java java-8 java-stream spliterator

6
推荐指数
1
解决办法
314
查看次数

如何限制Stream按顺序运行,并阻止它并行运行?

我有一个方法返回从自定义spliterator生成的流; 分裂器不是安全的.由于分裂器不是踏板安全的,并且它保持状态,我想防止它并行运行.有没有办法阻止返回的流并行运行?

我无法找到任何执行此操作的文档或示例.我确实sequential()BaseStream类上找到了一个方法,但这似乎并没有阻止用户调用parallel()以获得并行流.

java java-stream spliterator

6
推荐指数
1
解决办法
734
查看次数

在Spliterator的.tryAdance()的实现中,是否有任何危险来执行.accept()多个元素?

javadoc Spliterator提到:

Spliterator可以单独遍历元素(tryAdvance())或顺序遍历元素(forEachRemaining()).

然后我们转到javadoc,tryAdvance()其中说:

如果存在剩余元素,则对其执行给定操作,返回true; else返回false.

也许我在某个地方误读,但对我来说似乎只要剩下一个或多个元素,Consumer作为一个参数应该只.accept()返回前的每个参数true,如果,比方说,我有两个参数立即可用,那么我不能:

action.accept(arg1);
action.accept(arg2);
return true;
Run Code Online (Sandbox Code Playgroud)

这个项目中,我重写了广泛的第一个分裂器,现在它读取:

// deque is a Deque<Iterator<T>>

@Override
public boolean tryAdvance(final Consumer<? super T> action)
{
    Iterator<T> iterator;
    T element;

    while (!deque.isEmpty()) {
        iterator = deque.removeFirst();
        while (iterator.hasNext()) {
            element = iterator.next();
            deque.add(fn.apply(element));
            action.accept(element);
        }
    }
    return false;
}
Run Code Online (Sandbox Code Playgroud)

简而言之,我action接受所有参数,然后返回false ...而测试虽然很简单,但仍然成功(链接).

请注意,.trySplit()始终返回null; 分裂器具有特征DISTINCT,ORDERED并且NONNULL …

java java-8 spliterator

6
推荐指数
1
解决办法
292
查看次数

Spliterator - 大小与子范围标志

https://docs.oracle.com/javase/8/docs/api/java/util/Spliterator.html

SIZED特征值表示在遍历或拆分之前从estimateSize()返回的值表示有限大小,在没有结构源修改的情况下,表示完整遍历将遇到的元素数量的精确计数.

SUBSIZED特征值表示由trySplit()生成的所有Spliterator都将是SIZED和SUBSIZED.

  1. 是否存在SIZED标志打开但SUBSIZED标志关闭的情况?
  2. 是否存在SUBSIZED标志打开但SIZED标志关闭的情况?

java java-8 java-stream spliterator

6
推荐指数
1
解决办法
341
查看次数

为什么Spliterators.spliteratorUnknownSize()不是后期绑定?

我今天读了一下spliterators并实现了一个使用Spliterators.spliteratorUnknownSize(iterator(), Spliterator.NONNULL).根据spliteratorUnknownSize()文件

[结果]分裂器不是后期绑定的

作为分裂者的新手,我想知道为什么会这样.如果我确保iterator()后期绑定,那么得到的分裂器也应该是,不是吗? spliteratorUnknownSize()仅仅创建一个IteratorSpliterator不与元素源绑定的东西.

也就是说,我很想理解为什么得到的分裂器没有后期绑定.谢谢.

java late-binding spliterator

6
推荐指数
1
解决办法
206
查看次数

标签 统计

java ×10

spliterator ×10

java-8 ×8

java-stream ×7

builder ×1

late-binding ×1