如何在 Iterable 上执行 Stream 函数? [复制]

Posted

技术标签:

【中文标题】如何在 Iterable 上执行 Stream 函数? [复制]【英文标题】:How to perform Stream functions on an Iterable? [duplicate] 【发布时间】:2013-12-17 02:14:34 【问题描述】:

在 Java 8 中,Stream 类没有任何方法来包装 Iterable

相反,我从Iterable 获取Spliterator,然后从StreamSupport 获取Stream,如下所示:

boolean parallel = true;

StreamSupport.stream(spliterator(), parallel)
                .filter(Row::isEmpty)
                .collect(Collectors.toList())
                .forEach(this::deleteRow);

是否有其他方法可以在我缺少的 Iterable 上生成 Stream 操作?

【问题讨论】:

你的做法有什么问题?大多数Iterables都是Collection的实例,Collection有stream()和parallelStream()。 那么问题是为什么stream() 没有被拉入Iterable? 在这里回答:***.com/questions/23114015/… 【参考方案1】:

我的类似问题被标记为重复,但这里是我用来避免一些样板的帮助方法:

public static <T> Stream<T> stream(Iterable<T> in) 
    return StreamSupport.stream(in.spliterator(), false);


public static <T> Stream<T> parallelStream(Iterable<T> in) 
    return StreamSupport.stream(in.spliterator(), true);

【讨论】:

【参考方案2】:

我知道这并不能直接回答您的问题,但是相当数量的 Iterable 源(例如集合)现在也具有将对象作为流获取的方法。

我认为您会遇到这个问题的摩擦是 Iterable 在语义上是串行的,而 Spliterators 旨在用于并行处理。如果 JDK 中还没有提供您感兴趣的底层数据源,那么为您感兴趣的基础数据源实现 Spliterator 可能是一个更好的主意,因为仅使用 Iterable 周围的包装器不会让您获得 Stream API 提供的好处(如并行处理)。

【讨论】:

但是允许collection.stream(),但不允许iterable.stream(),同时提供iterable.spliterator(),背后的逻辑是什么?如果Iterable 没有提供spliterator(),您的回答将适用。 我猜它是为了阻止而不是禁止。您可以将由迭代器支持的流标记为并行,但您可能看不到好处。 另外,看看 implNote,他们为迭代器添加了 spliterator 方法 @implNote 默认实现通常应该被覆盖。默认实现返回的拆分器的拆分能力很差,没有大小,并且不报告任何拆分器特征。实现类几乎总能提供更好的实现。 a) 使用流比并行计算有更多的好处; b)当然默认的拆分器就是你所说的,当然它应该在一个大小的集合中被覆盖。但实现说明与接口定义无关。我被剥夺了任意Iterable 上的stream 方法,我不得不破解它。 Iterable#spliterator 确实提供了(正如他们所说的“有限”)并行性,这对于许多管道来说实际上非常好——确实非常好。这一事实主要抹黑了您关于Iterable 是“语义连续”的第二点。您的最后一句话以彻头彻尾的谎言告终:我个人一直在使用Iterabledefault Spliterator 来实现非常好的并行性。【参考方案3】:

您所描述的从 Iterable 获取流的方式。这就是他们将 spliterator() 方法添加到 Iterable 的原因。我自己也做过同样的转换,还没有看到其他方法。

[更新] 也许这个other answer 会澄清“为什么”。

【讨论】:

为什么他们让我们受苦... :P @SaintHill 因为 java 8 的非官方 moto 是“由学究,为学究”我有点担心这是开源的直接结果。那个,并且需要五年时间才能发货。 哈哈。我仍然很生气,他们无法通过添加像 toList 这样的合理默认值来让开发人员的生活更轻松,而无需费力输入 .collect(Collectors.toList()) !!!! 我认为您的意图是静态导入收集器,因此您只需键入 .collect(toList())。在公共 API 中有太多东西可能会在某种程度上成为噪音。我不希望看到所有的 Collectors.* 都附加到流 API。 @Jay 您指向另一个答案的链接解释了一个不同的问题,这就是为什么Stream 本身不是Iterable。其理由不适用于此处。

以上是关于如何在 Iterable 上执行 Stream 函数? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

为啥 Iterable<T> 不提供 stream() 和 parallelStream() 方法?

泛函编程(13)-无穷数据流-Infinite Stream

我应该如何检查 Stream<T> 是不是已排序?

Java 8 stream try

Stream-数据操作

Stream和迭代器的区别