Is there a common Java utility to break a list into batches?
Check out Lists.partition(java.util.List, int)
from Google Guava:
Returns consecutive sublists of a list, each of the same size (the final list may be smaller). For example, partitioning a list containing
[a, b, c, d, e]
with a partition size of 3 yields[[a, b, c]
,[d, e]]
-- an outer list containing two inner lists of three and two elements, all in the original order.
In case you want to produce a Java-8 stream of batches, you can try the following code:
public static <T> Stream<List<T>> batches(List<T> source, int length) {
if (length <= 0)
throw new IllegalArgumentException("length = " + length);
int size = source.size();
if (size <= 0)
return Stream.empty();
int fullChunks = (size - 1) / length;
return IntStream.range(0, fullChunks + 1).mapToObj(
n -> source.subList(n * length, n == fullChunks ? size : (n + 1) * length));
}
public static void main(String[] args) {
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14);
System.out.println("By 3:");
batches(list, 3).forEach(System.out::println);
System.out.println("By 4:");
batches(list, 4).forEach(System.out::println);
}
Output:
By 3:
[1, 2, 3]
[4, 5, 6]
[7, 8, 9]
[10, 11, 12]
[13, 14]
By 4:
[1, 2, 3, 4]
[5, 6, 7, 8]
[9, 10, 11, 12]
[13, 14]
Use Apache Commons ListUtils.partition.
org.apache.commons.collections4.ListUtils.partition(final List<T> list, final int size)
Another approach is to use Collectors.groupingBy
of indices and then map the grouped indices to the actual elements:
final List<Integer> numbers = range(1, 12)
.boxed()
.collect(toList());
System.out.println(numbers);
final List<List<Integer>> groups = range(0, numbers.size())
.boxed()
.collect(groupingBy(index -> index / 4))
.values()
.stream()
.map(indices -> indices
.stream()
.map(numbers::get)
.collect(toList()))
.collect(toList());
System.out.println(groups);
Output:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
[[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11]]