How can we create batches of Arraylist in Java 8?
Asked Answered
R

2

5

I get Arraylist of object of say 1000 elements and i want to create batch of 100.

How to do it in java 8 in some elegant way?

I have following entity to iterate upon which has size of 1000:

List<CustomerAgreement> customerAgreement 

Now i will call following methods after above

    customerAgreementDao.createAll(customerAgreement);
        customerAgreementDao.flush();

How can i create batches from above entity and call above two methods in that batch?

Current Standard way of doing this is somewhat like:

Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
for  ( int i=0; i<888888; i++ ) {
    TableA record = new TableA();
    record.setXXXX();
    session.save(record)
    if ( i % 50 == 0 ) { 
        session.flush();
        session.clear();
    }
}
tx.commit();
session.close();
Register answered 29/11, 2019 at 4:40 Comment(9)
@MaartenBodewes: Updated tags for database too but here i am just looking Java 8 way to create batches. I am taking it is general scenario where database is one of it. ThanksRegister
@MaartenBodewes: Ok you mean i should int batchForInsertsSize; initialValue = 0; int totalSize = customerAgreement.size(); and just create loop using totalsize/batchForInsertsSize and in that loop just change initialvalue and batchforinsertssize+initial value??? Isn't it standard way to do so?Register
since you are doing terminal operation and also you are not returning anything, in that case you can design Consumer to your needsDichotomy
@emotionlessbananas: Could you please give me some example.Register
I can try making one. Till then check for Stream#forEach(), which is similar you are looking forDichotomy
@Register That would be a way to go about it yes. No doubt there are others, maybe even including lambda's as emotionlessbananas will be trying to show you.Weissmann
I agree with @MaartenBodewes. Only thing I have got so for is some fancy,buggy implementation for your code reference and here it is: public void consumerTest() { AtomicInteger ai = new AtomicInteger(0); IntStream.range(0, 100).boxed().map(Table::new) .forEach(r -> this.forEachConsumer(r, ai.addAndGet(1))); } public void forEachConsumer(Table table, Integer counter) { System.out.println(counter); if (counter % 30 == 0) { System.err.println(counter); } } and I will not recommend this code inside productionDichotomy
I see that you've asked quite a lot of questions the last few days. Don't forget to follow up on them! Accept answers or indicate why they are not sufficient.Weissmann
@MaartenBodewes: Sure. Actually i am working on several modules in parallel and for many of them i am beginner. :( (Java CDI, Boot, Mongo, now throwing me into docker and quarkus thing) . I will surely accept answer once i implement the logic and it works fine. Regarding this question, i am stuck with CDI part so not able to tested (#59104745). So most questions are related to one another.Register
W
4

I'd myself use List.subList, as I'm not so into lambda's; they generally make your code less readable in my opinion.

This should work - if you don't mind I've scaled back on the array:

// create list as demo
var list = new ArrayList<String>();
for (int i = 0; i < 13; i++) {
    list.add(Integer.toString(i));
}

int batchSize = 3;

// the code
int offset = 0;
while (offset < list.size()) {
    // make sure the end offset doesn't go past the end
    int endOffset = Math.min(offset + batchSize, list.size());

    // call or add it to anything else, or even use streaming afterwards
    System.out.println(list.subList(offset, endOffset));
    offset = endOffset;
}

results in

[0, 1, 2]
[3, 4, 5]
[6, 7, 8]
[9, 10, 11]
[12]

Beware that the sublists are not copies, any changes to the objects in the list will be reflected in the sub lists, while structural changes (resizing) to the original list will result, well, probably in a mess. This also goes for the other way around, although structural changes to the subList are possible.

Weissmann answered 29/11, 2019 at 7:15 Comment(1)
Well, changes to any objects that aren't immutable such as Java String, obviously. No way of changing those without black art.Weissmann
M
2
    int itemsPerBatch = 100;
    int totalBatches = (customerAgreements.size()+itemsPerBatch-1)/itemsPerBatch;
    int offset = 0;
    for(int i=0; i<totalBatches; i++) {
        List<String> currentBatch = customerAgreements.subList(offset, Math.min(offset+itemsPerBatch, customerAgreements.size()));
        offset+=itemsPerBatch;
    }
Marathon answered 29/11, 2019 at 5:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.