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
Look's like no, cause creating chunks means reducing stream, and reduce means termination. If you need to maintain stream nature and process chunks without collecting all data before here is my code (does not work for parallel streams):
private static BinaryOperator> processChunks(Consumer> consumer, int chunkSize) {
return (data, element) -> {
if (data.size() < chunkSize) {
data.addAll(element);
return data;
} else {
consumer.accept(data);
return element; // in fact it's new data list
}
};
}
private static Function> createList(int chunkSize) {
AtomicInteger limiter = new AtomicInteger(0);
return element -> {
limiter.incrementAndGet();
if (limiter.get() == 1) {
ArrayList list = new ArrayList<>(chunkSize);
list.add(element);
return list;
} else if (limiter.get() == chunkSize) {
limiter.set(0);
}
return Collections.singletonList(element);
};
}
and how to use
Consumer> chunkProcessor = (list) -> list.forEach(System.out::println);
int chunkSize = 3;
Stream.generate(StrTokenizer::getInt).limit(13)
.map(createList(chunkSize))
.reduce(processChunks(chunkProcessor, chunkSize))
.ifPresent(chunkProcessor);
static Integer i = 0;
static Integer getInt()
{
System.out.println("next");
return i++;
}
it will print
next next next next 0 1 2 next next next 3 4 5 next next next 6 7 8 next next next 9 10 11 12
the idea behind is to create lists in a map operation with 'pattern'
[1,,],[2],[3],[4,,]...
and merge (+process) that with reduce.
[1,2,3],[4,5,6],...
and don't forget to process the last 'trimmed' chunk with
.ifPresent(chunkProcessor);