Is there an elegant way to process a stream in chunks?

前端 未结 7 2041
青春惊慌失措
青春惊慌失措 2020-12-08 00:26

My exact scenario is inserting data to database in batches, so I want to accumulate DOM objects then every 1000, flush them.

I implemented it by putting code in the

7条回答
  •  悲哀的现实
    2020-12-08 00:46

    As Misha rightfully said, Elegance is in the eye of the beholder. I personally think an elegant solution would be to let the class that inserts to the database do this task. Similar to a BufferedWriter. This way it does not depend on your original data structure and can be used even with multiple streams after one and another. I am not sure if this is exactly what you mean by having the code in the accumulator which you thought is wrong. I don't think it is wrong, since the existing classes like BufferedWriter work this way. You have some flush control from the caller this way by calling flush() on the writer at any point.

    Something like the following code.

    class BufferedDatabaseWriter implements Flushable {
        List buffer = new LinkedList();
        public void write(DomObject o) {
            buffer.add(o);
            if(buffer.length > 1000)
                flush();
        }
        public void flush() {
            //write buffer to database and clear it
        }
    }
    

    Now your stream gets processed like this:

    BufferedDatabaseWriter writer = new BufferedDatabaseWriter();
    stream.forEach(o -> writer.write(o));
    //if you have more streams stream2.forEach(o -> writer.write(o));
    writer.flush();
    

    If you want to work multithreaded, you could run the flush asynchronous. The taking from the stream can't go in parallel but I don't think there is a way to count 1000 elements from a stream in parallel anyway.

    You can also extend the writer to allow setting of the buffer size in constructor or you can make it implement AutoCloseable and run it in a try with ressources and more. The nice things you have from a BufferedWriter.

提交回复
热议问题