创建基于自定义生成器/迭代器方法的流

问题描述

如何创建基于自定义generate()方法创建多个项目的Stream?

问题与所提到的问题不同。最终结果是一个Stream,因此我可以(简单地)使用“ .forach(System.out :: println)”。>

一个例子是:Stream.generate(myGenerateMethod).forEach(System.out :: println);

或者一个简单的例子是:

Stream<String> overallStream = Stream.generate( () -> {
    if( generateCounter++ < 5) {
        return "String-" + generateCounter;
    }
    // close the stream
    return null; 
});
overallStream.forEach( System.out::println) ;

更新和解决方:提到的答案通常不会给出信息流。所以重新打开比较好。

maxGenerateCounter = 6;
StreamSupport.stream(Spliterators.spliteratorUnkNownSize(new Iterator<String>() {
    int counter = 0;

    @Override
    public boolean hasNext() {
        return counter < maxGenerateCounter;
    }

    @Override
    public String next() {
        // do something
        // check if the 'end' of the Stream is reached
        counter++; // simplistically
        if( counter > maxGenerateCounter) {
            return null; // Not important answer
        }
        return "String-" + counter;
    }
},Spliterator.IMMUTABLE),false).forEach( System.out::println);

解决方法

您已经回答了自己的问题。您的摘要正是您的操作方式。请注意,Stream.generate(lambda)仅适用于无限流(您不能标记流已结束),因此,Stream.generate的javadoc为什么以文本开头:“返回 infinite >顺序...”。

然后您可以使用limit对此进行限制。例如:

AtomicInteger counter = new AtomicInteger();
Stream<String> stream = Stream
    .generate(() -> "String-" + count.getAndIncrement())
    .limit(5)
    ;

请注意,takeWhile很有用,因此您的限制器本身也可以是lambda,例如:


AtomicInteger counter = new AtomicInteger();
Stream<String> stream = Stream
    .generate(() -> "String-" + count.getAndIncrement())
    .takeWhile(count.get() < 5)
    ;

但是takeWhile不在8中(它在11以上)。

另一种替代方法是制作自己的分离器,但这相当复杂。

第三种选择是进行自定义集合并依靠其迭代/流功能:

class StringGenerator extends AbstractList<String> {
    private final int size;
    public StringGenerator(int size) { this.size = size; }

    public int size() { return size; }
    public String get(int idx) { return "String-" + idx; }
}

...

new StringGenerator(5).stream().forEach(System.out::println);
,

更实用的写法是:

IntStream.iterate(0,i -> i < 5,i -> i + 1)
    .mapToObj(i -> "String-" + i)
    .forEach(System.out::println);

从零开始,在i < 5期间继续产生元素。对于每个步骤,请添加1:i -> i + 1

,

谢谢开发人员!您启发了我寻找解决方案。 非常感谢!

我的问题有点复杂,将其简化为一个过于简化的问题。

我们可以阅读许多解决方案,看起来Java和Streams很有趣!

通过许多答案进行实验,这一方法有效。 它为获得易于控制的STREAM提供了一种相当简单的方法。无需仔细检查标准。我喜欢那些能提供真知灼见的anyXxx()答案!

maxGenerateCounter = 6;
System.out.println( "Using Splitter: ");
StreamSupport.stream(Spliterators.spliteratorUnknownSize(new Iterator<String>() {
    int counter = 0;
    @Override
    public boolean hasNext() {
        // simplistic solution,see below for explanation
        return counter < maxGenerateCounter;
    }
    @Override
    public String next() {
        // executing stuff
        // providing info for 'stopping' the stream
        counter++; // for simplicity
        if( counter > maxGenerateCounter) {
           return null; // this could be any answer. It will be filtered out. 
        }
        return "String-" + counter;
    }
},Spliterator.IMMUTABLE),false).forEach( System.out::println);

再次感谢贡献者!