【问题标题】:Convert Iterable to Stream using Java 8 JDK使用 Java 8 JDK 将 Iterable 转换为 Stream
【发布时间】:2014-07-18 21:11:59
【问题描述】:

我有一个返回java.lang.Iterable<T>的接口。

我想使用 Java 8 Stream API 来处理该结果。

但是 Iterable 不能“流式传输”。

知道如何在不将 Iterable 转换为 List 的情况下将 Iterable 用作 Stream 吗?

【问题讨论】:

  • 如果你可以迭代,为什么不简单地使用循环来检查它的条件或值或者什么?
  • @AfzaalAhmadZeeshan 因为流更好
  • 正如我所说,我需要对该列表进行一些操作(过滤器、映射)。我想使用新的 Java 8 JDK API -> Stream。但 Iterable 不是“SteamAble”
  • myIterable.stream() 不存在似乎很奇怪!
  • @Guillaume:是的,但是Stream.of(iterable) 产生Stream<Iterable<Object>>

标签: java java-8 java-stream iterable


【解决方案1】:

您可以从IterableIterator 轻松创建Stream

public static <T> Stream<T> stream(Iterable<T> iterable) {
    return StreamSupport.stream(
        Spliterators.spliteratorUnknownSize(
            iterable.iterator(),
            Spliterator.ORDERED
        ),
        false
    );
}

【讨论】:

  • 你必须写一次这个函数然后调用它。为什么调用stream(...) 会使您的代码混乱?
  • 想要做它内联简短而优雅..你说得对,我可以写一次这个函数..但我正在删除代码(而不是添加代码)。无论如何,这个答案是正确的,因为这就是转换它的方法。
  • 静态导入表示函数。短而优雅。 (虽然不一定是透明的)
【解决方案2】:

有一个比直接使用spliteratorUnknownSize 更好的答案,这既更容易,也能获得更好的结果。 Iterable 有一个 spliterator() 方法,所以你应该用它来获得你的分离器。在最坏的情况下,它是相同的代码(默认实现使用spliteratorUnknownSize),但在更常见的情况下,您的Iterable 已经是一个集合,您将获得更好的拆分器,因此更好的流性能(甚至可能有很好的并行性)。它的代码也更少:

StreamSupport.stream(iterable.spliterator(), false)
             .filter(...)
             .moreStreamOps(...);

如您所见,从Iterable(另见this question)获取流并不是很痛苦。

【讨论】:

  • Stream 上的静态方法会很好,例如Stream.ofIterable(iterable).
  • @robinst 这不是遗漏;这是一个深思熟虑(且备受争议)的选择。挑战在于,如果它存在,那么在不了解随之而来的权衡的情况下,它太容易实现了。因为 Iterable 是如此抽象,所以这种方法可能会导致性能最差的流(没有并行支持,没有大小信息或特征(用于优化执行选择))。强迫更多的思考会在整个生态系统中产生更好的 API。这是“什么最适合 XYZ 代码”与“什么最适合所有 Java 代码”的权衡。
  • 根据你的解释,我很好奇为什么我们得到了 Collection.stream() 而不是 Iterable.stream()。似乎省略 Iterable.stream()(或 Stream.ofIterable())的理由同样适用于 Collection.stream()。
  • @BrianGoetz 看起来大多数人都没有达到理解你上面所说的或不在乎的水平。他们只想通过调用简单的 API 来编写简单的代码。另一方面,这些东西(并行...)对于大多数日常可迭代操作来说可能并不重要。
【解决方案3】:

我想建议使用 JOOL 库,它隐藏了 Seq.seq(iterable) 调用背后的拆分器魔法,还提供了一大堆额外的有用功能。

【讨论】:

    【解决方案4】:

    我已经创建了这个类:

    public class Streams {
        /**
         * Converts Iterable to stream
         */
        public static <T> Stream<T>  streamOf(final Iterable<T> iterable) {
            return toStream(iterable, false);
        }
    
        /**
         * Converts Iterable to parallel stream
         */
        public static <T> Stream<T> parallelStreamOf(final Iterable<T> iterable) {
            return toStream(iterable, true);
        }
    
        private static <T> Stream<T> toStream(final Iterable<T> iterable, final boolean isParallel) {
            return StreamSupport.stream(iterable.spliterator(), isParallel);
        }
    }
    

    我认为它非常易读,因为您不必考虑拆分器和布尔值 (isParallel)。

    【讨论】:

      【解决方案5】:

      如果你可以使用 Guava 库,从 21 版本开始,你可以使用

      Streams.stream(iterable)
      

      【讨论】:

      【解决方案6】:

      解决此问题的一个非常简单的解决方法是创建一个扩展 Iterable&lt;T&gt;Streamable&lt;T&gt; 接口,该接口包含一个 default &lt;T&gt; stream() 方法。

      interface Streamable<T> extends Iterable<T> {
          default Stream<T> stream() {
              return StreamSupport.stream(spliterator(), false);
          }
      }
      

      现在您的任何Iterable&lt;T&gt;s 都可以通过声明implements Streamable&lt;T&gt; 而不是Iterable&lt;T&gt; 轻松实现流式传输。

      【讨论】:

        【解决方案7】:

        如果你碰巧使用了 Vavr(以前称为 Javaslang),这可以很简单:

        Iterable i = //...
        Stream.ofAll(i);
        

        【讨论】:

          【解决方案8】:

          所以正如另一个答案提到的番石榴通过使用支持这一点:

          Streams.stream(iterable);
          

          我想强调的是,该实现与建议的其他答案略有不同。如果 IterableCollection 类型,他们会强制转换它。

          public static <T> Stream<T> stream(Iterable<T> iterable) {
            return (iterable instanceof Collection)
              ? ((Collection<T>) iterable).stream()
              : StreamSupport.stream(iterable.spliterator(), false);
          }
          
          public static <T> Stream<T> stream(Iterator<T> iterator) {
            return StreamSupport.stream(
              Spliterators.spliteratorUnknownSize(iterator, 0),
              false
            );
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2019-12-06
            • 2017-06-16
            • 2016-07-28
            • 1970-01-01
            • 2010-11-07
            • 2018-05-03
            相关资源
            最近更新 更多