I want to convert this java do...while() to a Java 8.
private static final Integer PAGE_SIZE = 200;
int offset = 0;
Page page = null;
do {
// Get all items.
page = apiService.get(selector);
// Display items.
if (page.getEntries() != null) {
for (Item item : page.getEntries()) {
System.out.printf("Item with name '%s' and ID %d was found.%n", item.getName(),
item.getId());
}
} else {
System.out.println("No items were found.");
}
offset += PAGE_SIZE;
selector = builder.increaseOffsetBy(PAGE_SIZE).build();
} while (offset < page.getTotalNumEntries());
This code makes api call to apiService
and retrieves data. Then, I want to loop until offset is less than totalNumberEntries
.
What is prohibiting me from using while()
or foreach with step
or any other kind of loop
loop is I don't know the totalNumberEntries
without making API call (which is done inside the loop).
One option I can think of is making the API call just to get the totalNumberEntries
and proceed with the loop.
If you really want/need a stream api for retrieving pages, you could create your own streams by implementing a Spliterator to retrieve each page in its tryAdvance() method.
It would look something like this
public class PageSpliterator implements Spliterator<Page> {
private static final Integer PAGE_SIZE = 200;
int offset;
ApiService apiService;
int selector;
Builder builder;
Page page;
public PageSpliterator(ApiService apiService) {
// initialize Builder?
}
@Override
public boolean tryAdvance(Consumer<? super Page> action) {
if (page == null || offset < page.getTotalNumEntries()) {
Objects.requireNonNull(action);
page = apiService.get(selector);
action.accept(page);
offset += PAGE_SIZE;
selector = builder.increaseOffsetBy(PAGE_SIZE).build();
return true;
} else {
// Maybe close/cleanup apiService?
return false;
}
}
@Override
public Spliterator<Page> trySplit() {
return null; // can't split
}
@Override
public long estimateSize() {
return Long.MAX_VALUE; // don't know in advance
}
@Override
public int characteristics() {
return IMMUTABLE; // return appropriate
}
}
Then you could use the it like this:
StreamSupport.stream(new PageSpliterator(apiService), false)
.flatMap(page -> page.getEntries()
.stream())
.forEach(item -> System.out.printf("Item with name '%s' and ID %d was found.%n", item.getName(), item.getId()));
In my opinion there are not many scenarios where a do...while loop would be the best choice. This however is such a scenario.
Just because there is new stuff in Java8, does not mean you have to use it. If you still want to implement it with a foreach loop, for whatever reason, then I would go for the option you mentioned. Do the API call at the beginning and then start the foreach.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With