java - 从头开始或从迭代器创建流

标签 java java-8 java-stream

我想不出创建 Stream 的好方法从头开始。假设例如(注意,下面的代码只是为了讨论的一个例子)

Matcher m = Pattern.compile(re).matcher(input);
List<String> matches = new ArrayList<>();
while (m.find())
    matches.add(m.group());

并希望利用流 API。我想做一些类似的事情

List<String> matches = Stream.of(() -> m.find(), () -> m.group())
                             .collect(Collectors.toList());

其中 () -> m.find() 是一个判断是否有更多元素的函数,而 () -> m.group() 是一个函数提供下一个元素。

创建一个 Iterator 很容易,例如:

class MatchIterator implements Iterator<String> {
    Matcher m;
    boolean hasNext;
    public MatchIterator(Matcher m) {
        this.m = m;
        hasNext = m.find();
    }
    @Override
    public boolean hasNext() {
        return hasNext;
    }
    @Override
    public String next() {
        String next = m.group();
        hasNext = m.find();
        return next;
    }
}

但我也想不出从迭代器创建流的简单方法。


编辑:我意识到我可以创建一个 Iterable 来创建 MatchIterator(然后使用 StreamSupport/Spliterator) 但这需要我能够多次迭代源代码,因此它仍然不是一个通用的解决方案。

最佳答案

要创建一个Stream,您需要一个Spliterator。然后使用 StreamSupport.stream() 创建一个 Stream。 (这是所有集合所做的。)

如果你已经有了一个Iterable,你可以从它的spliterator()方法中得到一个Spliterator(虽然你可能想写一个更好的一个;默认是弱的)。

如果您有一个Iterator,您可以使用Spliterators.spliteratorUnknownSize(Iterator) 将它变成一个Spliterator。 (同样,这会为您提供一个拆分器,但不一定是最佳拆分器。)

如果你两者都没有,你可以写一个Spliterator;它通常比编写 Iterator 更容易(实现更多方法,但通常更简单,因为您不必在 nexthasNext 之间重复逻辑.)

关于java - 从头开始或从迭代器创建流,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26255940/

相关文章:

java - Jtable 值复制最后一个值

当我将内容从文件转换到我的对象时,java抛出java.lang.ClassCastException

使用 lambda 的 List<> 的 Java8 子列表

java - 将两个不同的对象列表合并为一个具有共享 id 字段的对象列表

java - 该方法不适用于参数

java - 尝试在 GAE 开发环境中使用 restFB 时出错

java - 流和不同的操作

java - 我怎样才能将这段代码转换为Java 8

lambda - optional <List> Java 8 lambda 表达式获取第一个元素

java流: custom collector