How to Divide Lists into Sublists of Size N in Java


How can we divide lists into sublists of some size n in Java?

In other words, how can we partition lists into multiple sublists?

Suppose we want to process a sublist of our list in this processBatch() method.

void processBatch(List<Object> batch) { /* Process batch */ }

We might also have a List<Object> list and int batchSize.

1. Using Guava’s Lists.partition()

We can create the partitioned list using Lists.partition(), then process a batch on each iteration.

for (List<Object> batch : Lists.partition(list, batchSize)) {
  processBatch(batch);
}

We can also run this batch through a forEach().

Lists.partition(list, batchSize).forEach(this::processBatch);

2. Using Guava’s Iterators.partition()

If we’re working with a collection, but not a list, we can use Iterators.partition().

Similar to Lists.partition(), we can use a simple loop.

for (List<Object> batch : Iterators.partition(collection, batchSize)) {
  processBatch(batch);
}

Or, a forEach().

Iterators.partition(collection, batchSize).forEach(this::processBatch);

Guava Lists vs Iterators? If the list is an instance of the RandomAccess interface, then Lists will offer a performance benefit.

3. Using Apache Commons' ListUtils.partition()

Apache Commons' ListUtils functions the same way.

ListUtils.partition(list, batchSize).forEach(this::processBatch);

4. Using manual partitioning

We can also manually create the partitions.

List<List<Object>> batches = new ArrayList<>();
for (int i = 0; i < list.size(); i += batchSize) {
  batches.add(list.subList(i, Math.min(i + batchSize, list.size())));
}

Let’s try doing the same thing using streams.

List<List<Object>> batches = IntStream.range(0, list.size())
  .filter(i -> i % batchSize == 0)
  .mapToObj(i -> list.subList(i, Math.min(i + batchSize, list.size())))
  .collect(Collectors.toList());

Once the list of lists is created, we can simply iterate through and process each batch.

for (List<Object> batch : batches) {
  processBatch(batch)
}