How to Split a List Into Chunks in Java

Sheeraz Gul Feb 02, 2024
  1. Use the List.subList() Method to Split a List Into Chunks in Java
  2. Use Java Streams to Split a List Into Chunks in Java
  3. Use the Collectors.groupingBy() Method to Split a List Into Chunks in Java
  4. Use Apache Commons Collections Method to Split a List Into Chunks in Java
  5. Use Google Guava Library to Split a List Into Chunks in Java
  6. Conclusion
How to Split a List Into Chunks in Java

Splitting a list into smaller chunks is a common operation in Java, especially when dealing with large datasets or when implementing certain algorithms that require processing data in smaller portions. There are several approaches to achieve this in Java, each with its advantages and use cases.

Sometimes, it is required to split a list into a particular size of chunks in Java. This tutorial demonstrates different methods to split a list into chunks in Java.

Use the List.subList() Method to Split a List Into Chunks in Java

The subList() method in Java’s List interface allows us to create a view of a portion of an existing list. It takes two parameters: the starting index (inclusive) and the ending index (exclusive) of the sublist to be retrieved.

The resulting sublist is a view of the original list, meaning it maintains a reference to the original list’s elements without creating a new copy.

Syntax:

List<E> subList(int fromIndex, int toIndex)
  • fromIndex: The starting index (inclusive) of the sublist. The index of the first element in the sublist.
  • toIndex: The ending index (exclusive) of the sublist. The index after the last element in the sublist.

This method returns a view of the original list that contains elements from fromIndex up to toIndex - 1. The sublist is a view in the sense that it references the original list’s elements, allowing modifications in the sublist to affect the original list and vice versa.

For example:

  • list.subList(2, 5) returns a sublist that includes elements at indices 2, 3, and 4 from the original list.
  • The sublist includes elements starting from fromIndex up to, but not including, toIndex.

Keep in mind that if the original list is modified structurally (such as adding or removing elements) after creating a sublist, it can lead to unexpected behavior, including ConcurrentModificationException. Therefore, caution should be exercised when manipulating both the original list and its sublists simultaneously.

The List.subList method can be used along with a for loop to split a list into a particular size of chunks in Java. The subList() method will get a sublist from the given list within a specific start and end index.

Let’s see an example:

package delftstack;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

public class Example {
  public static void main(String[] args) {
    List<Integer> DemoList = IntStream.rangeClosed(100, 120).boxed().collect(Collectors.toList());
    int ChunkSize = 3;

    List<List<Integer>> Chunks = new ArrayList<>();

    for (int x = 0; x < DemoList.size(); x += ChunkSize) {
      Chunks.add(DemoList.subList(x, Math.min(x + ChunkSize, DemoList.size())));
    }

    System.out.println(Chunks);
  }
}

The code generates a list of integers from 100 to 120 and then splits this list into smaller chunks of size 3 using the subList() method. It iterates through the original list, creating sublists of the specified size and storing them in an ArrayList.

The code above will create chunks of size three from the given list. See the output:

List Chunk Output

This demonstrates a straightforward approach to dividing a list into smaller segments in Java, which is useful for managing and processing data in batches.

Use Java Streams to Split a List Into Chunks in Java

Similarly, we can use Java 9 IntStream.iterate() to split a list into chunks in Java.

The IntStream.iterate() method in Java creates an ordered sequence of primitive int-valued elements. It starts with an initial value (seed) and generates subsequent elements by applying a function to the previous element.

Syntax:

static IntStream iterate(int seed, IntUnaryOperator f)
  • seed: The initial value from which the iteration starts.
  • f: An IntUnaryOperator function that takes an integer and produces the next integer in the sequence.

Java Streams provide a functional and concise way to perform operations on collections. Splitting a list into smaller chunks using Java Streams involves leveraging functionalities like IntStream and collect() with Collectors.toList().

See the example:

package delftstack;

import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

public class Example {
  private static <T> List<List<T>> Chunks(List<T> DemoList, int ChunkSize) {
    return IntStream.iterate(0, x -> x < DemoList.size(), x -> x + ChunkSize)
        .mapToObj(x -> DemoList.subList(x, Math.min(x + ChunkSize, DemoList.size())))
        .collect(Collectors.toList());
  }

  public static void main(String[] args) {
    List<Integer> DemoList = IntStream.rangeClosed(100, 120).boxed().collect(Collectors.toList());
    int ChunkSize = 3;

    List<List<Integer>> Chunks = Chunks(DemoList, ChunkSize);
    System.out.println(Chunks);
  }
}

The code above will use IntStream.iterate() from Java 9 to perform the same operation as the previous method.

This code demonstrates how to split a list into chunks using Java Streams. The Chunks method takes a list (DemoList) and a chunk size (ChunkSize) as input and returns a list of lists representing the divided chunks.

This code efficiently utilizes Java Streams (IntStream.iterate(), mapToObj(), and collect()) to split the input list (DemoList) into smaller chunks based on the specified chunk size. The output displays the divided chunks as a list of lists.

List Chunk Output

We can also use Java 8 Stream API to perform the same operation. See example:

package delftstack;

import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

public class Example {
  private static <T> List<List<T>> Chunk(List<T> DemoList, int ChunkSize) {
    return IntStream.rangeClosed(0, (DemoList.size() - 1) / ChunkSize)
        .mapToObj(
            x -> DemoList.subList(x * ChunkSize, Math.min((x + 1) * ChunkSize, DemoList.size())))
        .collect(Collectors.toList());
  }

  public static void main(String[] args) {
    List<Integer> DemoList = IntStream.rangeClosed(100, 120).boxed().collect(Collectors.toList());
    int ChunkSize = 3;

    List<List<Integer>> Chunks = Chunk(DemoList, ChunkSize);
    System.out.println(Chunks);
  }
}

The code above will use Java 8 Stream API to split the list into three chunks. It demonstrates a method called Chunk within the Example class that splits a list (DemoList) into smaller sublists of a specified size (ChunkSize).

This code demonstrates an elegant use of Java Streams, specifically IntStream.rangeClosed, mapToObj, and collect, to efficiently split a list into smaller chunks based on a specified size, providing a reusable method for chunking lists.

See the output:

List Chunk Output

Use the Collectors.groupingBy() Method to Split a List Into Chunks in Java

The Collectors.groupingBy() method from Java Stream API can also be used to split a list into chunks, where we group by list elements to create chunks. This method will return the chunks in the form of Maps.

The Collectors.groupingBy() method is a powerful collector that allows you to partition elements of a Stream into groups based on a provided classification function. It returns a Map where the keys represent the grouping criteria, and the values are lists of elements that match each criterion.

Syntax:

Map<K, List<T>> result = yourStream.collect(
    Collectors.groupingBy(classifierFunction, // Function defining the grouping criterion
        downstreamCollector // Optional downstream collector (e.g., Collectors.toList())
        ));
  • yourStream: Represents the Stream instance containing elements to be grouped.
  • classifierFunction: This is a function that defines the criterion for grouping elements. It maps elements of the stream to keys of the resulting map. For example, if you want to group integers by their remainders when divided by 3, the classifier function might be: i -> i % 3.
  • downstreamCollector (Optional): This parameter specifies a downstream collector, allowing further operations on the grouped elements. For instance, Collectors.toList() collects the elements into a list for each group. It’s optional and can be omitted if you only need to group elements without any additional operations on the grouped values.
  • Map<K, List<T>> result: Represents the resulting map where keys of type K are the group criteria and values of type List<T> are the grouped elements.

Let’s see an example:

package delftstack;

import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

public class Example {
  private static <T> Collection<List<T>> Chunk(List<T> DemoList, int GroupBy) {
    return IntStream.range(0, DemoList.size())
        .boxed()
        .collect(Collectors.groupingBy(
            x -> x / GroupBy, Collectors.mapping(DemoList::get, Collectors.toList())))
        .values();
  }

  public static void main(String[] args) {
    List<Integer> DemoList = IntStream.rangeClosed(100, 120).boxed().collect(Collectors.toList());
    int ChunkSize = 3;

    Collection<List<Integer>> Chunks = Chunk(DemoList, ChunkSize);
    System.out.println(Chunks);
  }
}

This code demonstrates a method that efficiently partitions a list (DemoList) into chunks of a specified size (ChunkSize). It leverages Java Streams and collectors, particularly Collectors.groupingBy(), to perform the chunking operation based on indices and collect elements into separate lists within a collection.

The main() method showcases how to use this Chunk() method with a sample list of integers and print the resulting chunks.

See the output:

List Chunk Output

Similarly, we can simplify the above code by using a mutable counter. See the example:

package delftstack;

import java.util.Collection;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

public class Example {
  private static <T> Collection<List<T>> Chunk(List<T> DemoList, int Groupby) {
    AtomicInteger counter = new AtomicInteger();
    return DemoList.stream()
        .collect(Collectors.groupingBy(it -> counter.getAndIncrement() / Groupby))
        .values();
  }

  public static void main(String[] args) {
    List<Integer> DemoList = IntStream.rangeClosed(100, 120).boxed().collect(Collectors.toList());
    int ChunkSize = 3;

    Collection<List<Integer>> Chunks = Chunk(DemoList, ChunkSize);
    System.out.println(Chunks);
  }
}

The code above uses the mutable counter AtomicInteger to group by the list to create chunks of size three. It efficiently divides a given list into smaller chunks of a specified size using Java Streams and the Collectors.groupingBy collector, leveraging the index-based grouping technique.

See the output:

List Chunk Output

Use Apache Commons Collections Method to Split a List Into Chunks in Java

The Apache Commons is a third-party library that provides many operations, including a list. The collection from Apache Commons can also be used to create chunks of lists in Java.

First, make sure the Apache Commons Collections is added to your build path. Let’s try an example to create chunks of the list using Apache Commons Collections:

package delftstack;

import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import org.apache.commons.collections4.ListUtils;

public class Example {
  public static void main(String[] args) {
    List<Integer> DemoList = IntStream.rangeClosed(100, 120).boxed().collect(Collectors.toList());
    int ChunkSize = 3;

    List<List<Integer>> Chunks = ListUtils.partition(DemoList, ChunkSize);
    System.out.println(Chunks);
  }
}

The Apache Commons provides a method called partition, which is used to create chunks of the given list. This code demonstrates how to split a list of integers (DemoList) into smaller chunks of a specified size (ChunkSize) using the ListUtils.partition method from Apache Commons Collections.

The resulting chunks are stored in a list (Chunks) and displayed as output in the console when the code is executed.

List Chunk Output

Use Google Guava Library to Split a List Into Chunks in Java

The Guava package from Google also provides many functionalities regarding lists in Java. It provides a method, Lists.partition(), used to create chunks of a list in Java.

Please make sure the Guava package is added to your build path because it is a third-party package and not included in JDK. Let’s try an example:

package delftstack;

import com.google.common.collect.Lists;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

public class Example {
  public static void main(String[] args) {
    List<Integer> DemoList = IntStream.rangeClosed(100, 120).boxed().collect(Collectors.toList());
    int ChunkSize = 3;

    List<List<Integer>> Chunk = Lists.partition(DemoList, ChunkSize);
    System.out.println(Chunk);
  }
}

The code above will similarly create chunks of the given list in the form of three using the Guava library partition() method. It showcases the usage of Google Guava’s Lists.partition() method to efficiently split a list of integers into smaller chunks.

Google Guava provides a concise and convenient way to perform this operation without manually writing code for chunking. The resulting chunks are stored in a list and can be further utilized or processed based on the program’s requirements.

List Chunk Output

Conclusion

The tutorial explores diverse methods for splitting lists in Java into smaller chunks:

  1. List Subdivision (List.subList()):
    • Uses the subList() method to create view sublists based on indices, offering an efficient way to segment a list without copying elements.
  2. Java Streams Approach:
    • Showcases Java 8 and Java 9 Streams (IntStream.iterate() and IntStream.rangeClosed()) to split lists into chunks based on specified sizes, providing concise functional solutions.
  3. Collectors.groupingBy() from Java Stream API:
    • Highlights the powerful Collectors.groupingBy() method to categorize elements into chunks based on custom criteria, producing a Map of grouped elements.
  4. Third-party Libraries (Apache Commons Collections & Google Guava):
    • Introduces third-party methods (ListUtils.partition() from Apache Commons Collections and Lists.partition() from Google Guava) to simplify list splitting, offering convenient alternatives without custom logic.

Each method provides unique advantages, catering to different use cases and preferences and empowering developers to efficiently segment lists as needed.

Author: Sheeraz Gul
Sheeraz Gul avatar Sheeraz Gul avatar

Sheeraz is a Doctorate fellow in Computer Science at Northwestern Polytechnical University, Xian, China. He has 7 years of Software Development experience in AI, Web, Database, and Desktop technologies. He writes tutorials in Java, PHP, Python, GoLang, R, etc., to help beginners learn the field of Computer Science.

LinkedIn Facebook

Related Article - Java List