I have a method:
invokList(List
This method is inside a jar and I have no access to the source code of it. So for that
Looks very verbose, but you can try the following. The runAsync()
method will make the list chunks run in parallel.
private void test(List<Object> list, int chunkSize) throws ExecutionException, InterruptedException {
AtomicInteger prev = new AtomicInteger(0);
List<CompletableFuture> futures = new ArrayList<>();
IntStream.range(1, (int) (chunkSize * (Math.ceil(Math.abs(list.size() / (double) chunkSize)))))
.filter(i -> i % chunkSize == 0 || i == list.size())
.forEach(i -> {
List<Object> chunk = list.subList(prev.get(), i);
futures.add(CompletableFuture.runAsync(() -> invokeList(chunk)));
prev.set(i);
});
CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).get();
}
private void invokeList(List<Object> list) {
System.out.println("Invoked for: " + list);
}
I ran it for a list of 30 integers, with a chunk size of 5 like this:
public static void main(String[] args) throws ExecutionException, InterruptedException {
List<Object> list = IntStream.range(0, 30).mapToObj(i1 -> (Object) String.valueOf(i1)).collect(Collectors.toList());
int chunkSize = 5;
new Test().test(list, chunkSize);
}
Output:
Invoked for: [15, 16, 17, 18, 19]
Invoked for: [0, 1, 2, 3, 4]
Invoked for: [5, 6, 7, 8, 9]
Invoked for: [10, 11, 12, 13, 14]
Invoked for: [20, 21, 22, 23, 24]
Guava has methods Lists.partition and Iterables.partition that do something like what you're asking. Say you have a large List and want to process it in chunks of 5, you could do:
int batchSize = 5;
Lists.partition(list, batchSize)
.parallelStream()
.forEach(batch -> invokeList(batch));
if you don't want to bring additional dependencies like Guava, then you can write a collector which divide your list in chunks:
static <T> Collector<T, List<List<T>>, List<List<T>>> toChunks(int size) {
return Collector.of(ArrayList::new, (list, value) -> {
List<T> chunk = list.isEmpty() ? null : list.get(list.size() - 1);
if (chunk == null || chunk.size() == size) {
chunk = new ArrayList<>(size);
list.add(chunk);
}
chunk.add(value);
}, (list1, list2) -> {
throw new UnsupportedOperationException();
});
}
and then call it as follows:
List<Integer> list = Arrays.asList(1,26,17,18,19,20);
list.stream().collect(toChunks(5))
.parallelStream()
.forEach(System.out::println);