如何在Java中从动态源生成对象流?

如何在Java中从动态源生成对象流?,java,java-stream,Java,Java Stream,我正在尝试解决一个问题,看起来用Java是不可能的 我有一些调用processObject(SomeObject SomeObject)的代码和处理它的方法。我正试图封装这整件事,并希望得到一些对象流 下面是我的示例程序: import java.util.stream.Stream; public class ProcessObject { public static void main(String[] args) { int i = 0; Pro

我正在尝试解决一个问题,看起来用Java是不可能的

我有一些调用processObject(SomeObject SomeObject)的代码和处理它的方法。我正试图封装这整件事,并希望得到一些对象流

下面是我的示例程序:

import java.util.stream.Stream;

public class ProcessObject {

    public static void main(String[] args) {
        int i = 0;
        ProcessObject processObject = new ProcessObject();
        while (true) {
            processObject.processObject(new SomeObject("Hello " + i++));
        }
    }

    public void processObject(SomeObject someObject) {
        System.out.println(someObject);

    }
    //TODO
    public Stream<SomeObject> getStream(){
        //Producer here should wait and produce Objects as soon as 
        //they become available like "processObject" method.
        return Stream.generate(() -> new SomeObject("Hello "));
    }
}


class SomeObject {
    public String name;

    public SomeObject(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return name;
    }
}
import java.util.stream.stream;
公共类ProcessObject{
公共静态void main(字符串[]args){
int i=0;
ProcessObject ProcessObject=新的ProcessObject();
while(true){
processObject.processObject(新的SomeObject(“Hello”+i++”);
}
}
public void processObject(SomeObject SomeObject){
System.out.println(someObject);
}
//待办事项
公共流getStream(){
//此处的生产者应等待并尽快生成对象
//它们变得像“processObject”方法一样可用。
返回Stream.generate(()->newsomeobject(“Hello”);
}
}
类对象{
公共字符串名称;
公共对象(字符串名称){
this.name=名称;
}
@凌驾
公共字符串toString(){
返回名称;
}
}
静态main方法继续生成someobject,并调用processObject方法来处理它们,然后打印它们。所以,一切都很好

我想创建SomeObject的流,这样我就不用调用方法来处理它们,而是使用流来处理它们,类似这样:

公共流getStream()

现在有了Java8或Java9,就有了可用的流。但是把不可变特征的条件从生成它们的源中放出来

如何创建一个流,然后在元素像真正的管道一样可用时向流中添加元素?


我曾想过使用BlockingQueue并在流生成方法中使用它作为类似BlockingQueue.take()的生产者,但它从未编译过。

这里的问题是不能在lambda表达式中变异局部变量
I
,不是吗?因为lambda基本上是一个匿名的内部类,所以可以将
i
作为内部类的字段

Stream<String> stream = Stream.generate(new Supplier<String>() {
    int i = 0;
    // if you have any other state you want to mutate, put it here as well!
    @Override
    public String get() {
        return "Hello" + i++;
    }
});
// prints Hello0 to Hello9!
System.out.println(stream.limit(10).collect(Collectors.toList()));
Stream=Stream.generate(新供应商(){
int i=0;
//如果你有任何其他状态你想变异,把它也放在这里!
@凌驾
公共字符串get(){
返回“Hello”+i++;
}
});
//将他从0打印到9!
System.out.println(stream.limit(10.collect)(collector.toList());

要使用
阻塞队列
流提供数据
,您需要生产者和消费者在不同的线程上运行

在这里,我使用我的主线程来使用流,并使用一个新线程通过
阻塞队列
来演示

public void test(String[] args) {
    // My queue
    BlockingQueue<BigInteger> queue = new ArrayBlockingQueue<>(10);

    // A Stream of it's contents.
    Stream<BigInteger> biStream = Stream.generate(() -> {
        try {
            return queue.take();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    });

    // Feed the queue from a thread.
    new Thread(new Runnable() {
        // Must be final to be accessible inside `run`.
        final AtomicInteger i = new AtomicInteger();

        @Override
        public void run() {
            // Slow feed to the queue.
            while (true) {
                // Add a new number to the queue.
                queue.add(BigInteger.valueOf(i.getAndIncrement()));
                try {
                    Thread.sleep(200);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }).start();

    // DEMO - Consumes the queue printing contents as they arrive.
    biStream.filter(x -> x.testBit(2))
            .limit(20)
            .forEach(x -> System.out.println(x));
}
公共无效测试(字符串[]args){
//我的队列
BlockingQueue=new ArrayBlockingQueue(10);
//一系列的内容。
Stream biStream=Stream.generate(()->{
试一试{
返回队列。take();
}捕捉(中断异常e){
抛出新的运行时异常(e);
}
});
//从线程馈送队列。
新线程(newrunnable()){
//必须是最终版本,才能在“运行”中访问。
最终AtomicInteger i=新的AtomicInteger();
@凌驾
公开募捐{
//向队列缓慢馈送。
while(true){
//向队列中添加新编号。
add(biginger.valueOf(i.getAndIncrement());
试一试{
睡眠(200);
}捕捉(中断异常e){
e、 printStackTrace();
}
}
}
}).start();
//演示-在打印内容到达时使用队列打印内容。
双流过滤器(x->x.testBit(2))
.限额(20)
.forEach(x->System.out.println(x));
}

true BlockingQueue至少需要两个线程……我今晚会在家里尝试……谢谢:)我想我得到了我需要的。当没有新元素时,每秒醒来调用
queue.poll(1,TimeUnit.SECONDS)
又有什么意义呢?为什么不首先简单地调用
take()
?@Holger-很好。固定的!我试图安静地处理
中断异常
。@abcdef12没有两个线程,无论实现如何,都无法完成您想要的任务。如果当前线程正在等待数据到达,它将如何使数据可用?@daniu I采用了不同的方法来解决它。我根本不使用流。我现在使用阻塞队列,信号量。我创建了一个池,其中信号量控制生产者和消费者,并根据负载需求将线程分配给消费者/生产者。就像一个平衡器。