Class Chunking

java.lang.Object
dev.zachmaddox.chunking.Chunking

public final class Chunking extends Object
Utility class for chunking streams and iterables into lists.

All chunking methods preserve the encounter order of the input. In particular, collectors such as chunkedBy(BiPredicate) and weightedChunks(long, ToLongFunction) define their semantics in terms of adjacent elements in the encounter order. Supplying an unordered or non-deterministic stream may therefore produce non-deterministic chunk boundaries.

  • Method Details

    • toChunks

      public static <T> Collector<T,?,List<List<T>>> toChunks(int chunkSize)
      Returns a Collector that groups elements into chunks of chunkSize, including the final partial chunk if any.

      Works with any stream source (lists, sets, arrays via Arrays.stream, etc.).

      Type Parameters:
      T - the element type of the stream
      Parameters:
      chunkSize - the maximum number of elements in each chunk; must be greater than zero
      Returns:
      a collector that accumulates elements into a List<List<T>>
      Throws:
      IllegalArgumentException - if chunkSize is less than 1
    • toChunks

      public static <T> Collector<T,?,List<List<T>>> toChunks(int chunkSize, Chunking.RemainderPolicy remainderPolicy)
      Returns a Collector that groups elements into chunks of chunkSize, using the provided Chunking.RemainderPolicy.
      Type Parameters:
      T - the element type of the stream
      Parameters:
      chunkSize - the maximum number of elements in each chunk; must be greater than zero
      remainderPolicy - how to handle the final partial chunk; must not be null
      Returns:
      a collector that accumulates elements into a List<List<T>>
      Throws:
      IllegalArgumentException - if chunkSize is less than 1
      NullPointerException - if remainderPolicy is null
    • toChunks

      public static <T, C extends List<T>> Collector<T,?,List<C>> toChunks(int chunkSize, IntFunction<C> chunkFactory)
      Returns a Collector that groups elements into chunks of chunkSize, using a custom list implementation for each chunk.

      The chunkFactory is called once per chunk, with the intended size of that chunk (number of elements). Implementations may ignore the hint.

      The final partial chunk is included (equivalent to Chunking.RemainderPolicy.INCLUDE_PARTIAL).

      Type Parameters:
      T - the element type
      C - the list implementation used for chunks
      Parameters:
      chunkSize - the maximum number of elements in each chunk; must be greater than zero
      chunkFactory - factory used to create each chunk list; must not be null
      Returns:
      a collector that accumulates elements into a List<C>
      Throws:
      IllegalArgumentException - if chunkSize is less than 1
      NullPointerException - if chunkFactory is null
    • toChunks

      public static <T, C extends List<T>> Collector<T,?,List<C>> toChunks(int chunkSize, Chunking.RemainderPolicy remainderPolicy, IntFunction<C> chunkFactory)
      Returns a Collector that groups elements into chunks of chunkSize, using both a custom Chunking.RemainderPolicy and a custom chunk list implementation.
      Type Parameters:
      T - the element type
      C - the list implementation used for chunks
      Parameters:
      chunkSize - the maximum number of elements in each chunk; must be greater than zero
      remainderPolicy - how to handle the final partial chunk; must not be null
      chunkFactory - factory used to create each chunk list; must not be null
      Returns:
      a collector that accumulates elements into a List<C>
      Throws:
      IllegalArgumentException - if chunkSize is less than 1
      NullPointerException - if remainderPolicy or chunkFactory is null
    • toChunks

      public static <T, C extends List<T>, OC extends Collection<C>> Collector<T,?,OC> toChunks(int chunkSize, Chunking.RemainderPolicy remainderPolicy, IntFunction<C> chunkFactory, Supplier<OC> outerCollectionFactory)
      Returns a Collector that groups elements into chunks of chunkSize, using a custom Chunking.RemainderPolicy, a custom chunk list implementation, and a custom outer collection type.

      This overload is useful when you want the outer collection to be something other than a List, for example a LinkedHashSet of chunk lists.

      
       Collector<Integer, ?, LinkedHashSet<List<Integer>>> collector =
               Chunking.toChunks(
                       3,
                       RemainderPolicy.INCLUDE_PARTIAL,
                       ArrayList::new,
                       LinkedHashSet::new
               );
       
      Type Parameters:
      T - the element type
      C - the list implementation used for individual chunks
      OC - the outer collection type that will hold all chunks
      Parameters:
      chunkSize - the maximum number of elements in each chunk; must be greater than zero
      remainderPolicy - how to handle the final partial chunk; must not be null
      chunkFactory - factory used to create each chunk list; must not be null
      outerCollectionFactory - factory used to create the outer collection; must not be null
      Returns:
      a collector that accumulates elements into an OC
      Throws:
      IllegalArgumentException - if chunkSize is less than 1
      NullPointerException - if remainderPolicy, chunkFactory, or outerCollectionFactory is null
    • streamOfChunks

      public static <T> Stream<List<T>> streamOfChunks(Stream<T> source, int chunkSize)
      Returns a Stream of fixed-size chunks from the given source stream.

      The returned stream is lazy and consumes the source stream as it is traversed. Closing the returned stream will also close the source stream.

      The final partial chunk is included.

      Type Parameters:
      T - element type
      Parameters:
      source - the source stream; must not be null
      chunkSize - the maximum number of elements in each chunk; must be greater than zero
      Returns:
      a stream of chunks as List<T>
      Throws:
      NullPointerException - if source is null
      IllegalArgumentException - if chunkSize is less than 1
    • streamOfChunks

      public static <T> Stream<List<T>> streamOfChunks(Stream<T> source, int chunkSize, Chunking.RemainderPolicy remainderPolicy)
      Returns a Stream of fixed-size chunks from the given source stream, using the given Chunking.RemainderPolicy.

      The returned stream is lazy and consumes the source stream as it is traversed. Closing the returned stream will also close the source stream.

      Type Parameters:
      T - element type
      Parameters:
      source - the source stream; must not be null
      chunkSize - the maximum number of elements in each chunk; must be greater than zero
      remainderPolicy - how to handle the final partial chunk; must not be null
      Returns:
      a stream of chunks as List<T>
      Throws:
      NullPointerException - if source or remainderPolicy is null
      IllegalArgumentException - if chunkSize is less than 1
    • forEachChunk

      public static <T> void forEachChunk(Stream<T> source, int chunkSize, Consumer<? super List<T>> chunkHandler)
      Processes each fixed-size chunk from the given source stream using the provided consumer, without materializing all chunks in memory at once.

      This is a convenience wrapper around streamOfChunks(Stream, int) for the common "stream-and-handle-chunks" use case:

      
       Chunking.forEachChunk(
               someStream,
               100,
               chunk -> doSomethingWith(chunk)
       );
       

      The source stream is always closed when processing completes or if an exception is thrown.

      Type Parameters:
      T - element type
      Parameters:
      source - the source stream; must not be null
      chunkSize - the maximum number of elements in each chunk; must be greater than zero
      chunkHandler - consumer that will be invoked once per emitted chunk; must not be null
      Throws:
      NullPointerException - if source or chunkHandler is null
      IllegalArgumentException - if chunkSize is less than 1
    • forEachChunk

      public static <T> void forEachChunk(Stream<T> source, int chunkSize, Chunking.RemainderPolicy remainderPolicy, Consumer<? super List<T>> chunkHandler)
      Processes each fixed-size chunk from the given source stream using the provided consumer, with an explicit Chunking.RemainderPolicy.
      Type Parameters:
      T - element type
      Parameters:
      source - the source stream; must not be null
      chunkSize - the maximum number of elements in each chunk; must be greater than zero
      remainderPolicy - how to handle the final partial chunk; must not be null
      chunkHandler - consumer that will be invoked once per emitted chunk; must not be null
      Throws:
      NullPointerException - if source, remainderPolicy, or chunkHandler is null
      IllegalArgumentException - if chunkSize is less than 1
    • slidingWindows

      public static <T> Collector<T,?,List<List<T>>> slidingWindows(int windowSize, int step)
      Returns a Collector that produces sliding windows of size windowSize with step step.

      Only full windows are produced. For example:

       [1,2,3,4] with windowSize=3, step=1 → [[1,2,3],[2,3,4]]
       

      This collector respects the stream's encounter order and only makes sense for ordered streams; using an unordered stream will yield arbitrary windows.

      Type Parameters:
      T - element type
      Parameters:
      windowSize - the size of each window; must be greater than zero
      step - the step between window starting positions; must be greater than zero
      Returns:
      a collector that accumulates elements into sliding windows
      Throws:
      IllegalArgumentException - if windowSize or step is less than 1
    • streamOfSlidingWindows

      public static <T> Stream<List<T>> streamOfSlidingWindows(Stream<T> source, int windowSize)
      Returns a Stream of sliding windows of size windowSize with step 1.

      This is the streaming counterpart to slidingWindows(int, int), emitting each window lazily without retaining all windows in memory.

      Type Parameters:
      T - element type
      Parameters:
      source - the source stream; must not be null
      windowSize - the size of each window; must be greater than zero
      Returns:
      a stream of windows as List<T>
      Throws:
      NullPointerException - if source is null
      IllegalArgumentException - if windowSize is less than 1
    • streamOfSlidingWindows

      public static <T> Stream<List<T>> streamOfSlidingWindows(Stream<T> source, int windowSize, int step)
      Returns a Stream of sliding windows of size windowSize with the given step.

      Only full windows are produced. Semantics match slidingWindows(int, int) but in a streaming form.

      Type Parameters:
      T - element type
      Parameters:
      source - the source stream; must not be null
      windowSize - the size of each window; must be greater than zero
      step - the step between window starting positions; must be greater than zero
      Returns:
      a stream of windows as List<T>
      Throws:
      NullPointerException - if source is null
      IllegalArgumentException - if windowSize or step is less than 1
    • chunkedBy

      public static <T> Collector<T,?,List<List<T>>> chunkedBy(BiPredicate<? super T,? super T> sameGroup)
      Returns a Collector that groups elements into chunks based on a boundary predicate.

      The first element always starts a new chunk. For each subsequent element current, the predicate is called with (previous, current):

      • If it returns true, current is added to the current chunk.
      • If it returns false, a new chunk is started with current.

      Ordering note: this collector defines its semantics in terms of adjacent elements in the stream's encounter order. If you supply an unordered or non-deterministic stream (for example, a parallel stream without forcing .sequential()), the resulting chunk boundaries may be non-deterministic.

      Type Parameters:
      T - element type
      Parameters:
      sameGroup - predicate that determines whether two adjacent elements belong to the same chunk; must not be null
      Returns:
      a collector that accumulates elements into boundary-based chunks
      Throws:
      NullPointerException - if sameGroup is null
    • weightedChunks

      public static <T> Collector<T,?,List<List<T>>> weightedChunks(long maxWeight, ToLongFunction<? super T> weigher)
      Returns a Collector that groups elements into chunks such that the sum of weights (as provided by weigher) within each chunk is <= maxWeight.

      The semantics are:

      • Elements are processed in encounter order.
      • If adding an element would exceed maxWeight, a new chunk is started.
      • If a single element's weight is greater than maxWeight, it forms a chunk by itself.
      • Negative weights are not allowed.

      Ordering note: chunk composition is based purely on the stream's encounter order and the running sum of weights. If you collect from an unordered or non-deterministic stream, the grouping of elements into chunks may vary between runs.

      Type Parameters:
      T - element type
      Parameters:
      maxWeight - maximum total weight per chunk; must be greater than zero
      weigher - function that computes the weight of each element; must not be null
      Returns:
      a collector that accumulates elements into weighted chunks
      Throws:
      IllegalArgumentException - if maxWeight is less than 1
      NullPointerException - if weigher is null
    • chunk

      public static <T> List<List<T>> chunk(Iterable<T> iterable, int chunkSize)
      Chunks an Iterable into a list of lists, using its iteration order.

      The final partial chunk is included.

      Type Parameters:
      T - the element type
      Parameters:
      iterable - the source iterable; must not be null
      chunkSize - the maximum number of elements in each chunk; must be greater than zero
      Returns:
      a list of chunks; possibly empty if the iterable has no elements
      Throws:
      NullPointerException - if iterable is null
      IllegalArgumentException - if chunkSize is less than 1
    • chunk

      public static <T> List<List<T>> chunk(Spliterator<T> spliterator, int chunkSize)
      Chunks a Spliterator into a list of lists, using its traversal order.

      The final partial chunk is included.

      Type Parameters:
      T - the element type
      Parameters:
      spliterator - the source spliterator; must not be null
      chunkSize - the maximum number of elements in each chunk; must be greater than zero
      Returns:
      a list of chunks; possibly empty if the spliterator has no elements
      Throws:
      NullPointerException - if spliterator is null
      IllegalArgumentException - if chunkSize is less than 1
    • chunk

      public static <T> List<List<T>> chunk(Collection<T> collection, int chunkSize)
      Chunks a Collection into a list of lists, using its iteration order.

      The final partial chunk is included.

      Type Parameters:
      T - the element type
      Parameters:
      collection - the source collection; must not be null
      chunkSize - the maximum number of elements in each chunk; must be greater than zero
      Returns:
      a list of chunks; possibly empty if the collection is empty
      Throws:
      NullPointerException - if collection is null
      IllegalArgumentException - if chunkSize is less than 1
    • chunk

      public static <T> List<List<T>> chunk(Stream<T> stream, int chunkSize)
      Chunks a Stream into a list of lists and closes the stream.

      The final partial chunk is included.

      Type Parameters:
      T - the element type
      Parameters:
      stream - the source stream; must not be null
      chunkSize - the maximum number of elements in each chunk; must be greater than zero
      Returns:
      a list of chunks; possibly empty if the stream has no elements
      Throws:
      NullPointerException - if stream is null
      IllegalArgumentException - if chunkSize is less than 1
    • chunk

      @SafeVarargs public static <T> List<List<T>> chunk(int chunkSize, T... elements)
      Varargs convenience method: chunks an array of elements.

      The final partial chunk is included.

      Type Parameters:
      T - the element type
      Parameters:
      chunkSize - the maximum number of elements in each chunk; must be greater than zero
      elements - the elements to chunk; must not be null
      Returns:
      a list of chunks; possibly empty if no elements are provided
      Throws:
      NullPointerException - if elements is null
      IllegalArgumentException - if chunkSize is less than 1
    • chunk

      public static List<List<Integer>> chunk(IntStream stream, int chunkSize)
      Chunks an IntStream into List<List<Integer>> and closes it.

      The final partial chunk is included.

      Parameters:
      stream - the source int stream; must not be null
      chunkSize - the maximum number of elements in each chunk; must be greater than zero
      Returns:
      a list of chunks; possibly empty if the stream has no elements
      Throws:
      NullPointerException - if stream is null
      IllegalArgumentException - if chunkSize is less than 1
    • chunk

      public static List<List<Long>> chunk(LongStream stream, int chunkSize)
      Chunks a LongStream into List<List<Long>> and closes it.

      The final partial chunk is included.

      Parameters:
      stream - the source long stream; must not be null
      chunkSize - the maximum number of elements in each chunk; must be greater than zero
      Returns:
      a list of chunks; possibly empty if the stream has no elements
      Throws:
      NullPointerException - if stream is null
      IllegalArgumentException - if chunkSize is less than 1
    • chunk

      public static List<List<Double>> chunk(DoubleStream stream, int chunkSize)
      Chunks a DoubleStream into List<List<Double>> and closes it.

      The final partial chunk is included.

      Parameters:
      stream - the source double stream; must not be null
      chunkSize - the maximum number of elements in each chunk; must be greater than zero
      Returns:
      a list of chunks; possibly empty if the stream has no elements
      Throws:
      NullPointerException - if stream is null
      IllegalArgumentException - if chunkSize is less than 1
    • toIntChunks

      public static Collector<Integer,?,List<List<Integer>>> toIntChunks(int chunkSize)
      Convenience collector for IntStreams.
      Parameters:
      chunkSize - the maximum number of elements in each chunk; must be greater than zero
      Returns:
      a collector that accumulates Integer values into fixed-size chunks
      Throws:
      IllegalArgumentException - if chunkSize is less than 1
    • toLongChunks

      public static Collector<Long,?,List<List<Long>>> toLongChunks(int chunkSize)
      Convenience collector for LongStreams.
      Parameters:
      chunkSize - the maximum number of elements in each chunk; must be greater than zero
      Returns:
      a collector that accumulates Long values into fixed-size chunks
      Throws:
      IllegalArgumentException - if chunkSize is less than 1
    • toDoubleChunks

      public static Collector<Double,?,List<List<Double>>> toDoubleChunks(int chunkSize)
      Convenience collector for DoubleStreams.
      Parameters:
      chunkSize - the maximum number of elements in each chunk; must be greater than zero
      Returns:
      a collector that accumulates Double values into fixed-size chunks
      Throws:
      IllegalArgumentException - if chunkSize is less than 1