1. Introduction

Splitting a string into smaller, more manageable chunks is a common task in many programming scenarios. In Kotlin, there are various ways to achieve this, but it can be particularly useful when we need to process large strings or text data in a more organized manner.

In this tutorial, we’ll explore different techniques for splitting a String into chunks of a given size using the Kotlin programming language, and we’ll use JUnit tests to understand these techniques.

2. Understanding the Problem

Let’s imagine a common scenario: we have a String and want to split it into parts where each part is of a specific size, say n. If the string’s length is not a multiple of n, the last chunk may be smaller.

For example, if we have a string “HelloWorld” and we want to split it into chunks of size three, the result should be [“Hel”, “loW”, “orl”, “d”].

3. Using the chunked() Function

Kotlin provides a built-in chunked() function which makes this task straightforward. The chunked() function is part of the Kotlin standard library and it’s available on String and List types.

3.1. Basic Usage

Here’s how we can use chunked() to split a string:

val input = "HelloWorld"
val chunkSize = 3
val chunks = input.chunked(chunkSize)
assertEquals(chunks, listOf("Hel", "loW", "orl", "d"))

The chunked() function takes the desired size of each chunk as its argument and returns a List of strings, each of the specified size, except the last one which may be smaller.

3.2. Handling the Last Chunk

For cases where we need to ensure that the last chunk has a specific size, we can combine the chunked() function with padEnd(). This approach pads the String to a size that is a multiple of n before splitting it. The math behind padEnd() involves adding enough padding to make the total length a multiple of the chunk size.

Let’s apply it to our “HelloWorld” string:

val input = "HelloWorld"
val chunkSize = 3
val paddedInput = input.padEnd(input.length + chunkSize - (input.length % chunkSize), ' ')
val chunks = paddedInput.chunked(chunkSize)
assertEquals(chunks, listOf("Hel", "loW", "orl", "d  "))

Notably, this method may add extra characters, which may not be desirable in all cases.

4. Custom Chunking Using the windowed() Function

Kotlin also provides a windowed() function which can be used to get a sliding window of a given size over the string.

While windowed() isn’t directly meant for chunking, with a few adjustments, it can be used for this purpose:

val input = "HelloWorld"
val chunkSize = 3
val chunks = input.windowed(size = chunkSize, step = chunkSize, partialWindows = true)
assertEquals(chunks, listOf("Hel", "loW", "orl", "d"))

The partialWindows parameter tells the function to include the last window even if it’s smaller than the specified size.

5. Manual Approach

If we need to have more control over the process we can manually implement the chunking logic:

val input = "HelloWorld"
val chunkSize = 3
val chunks = mutableListOf<String>()

for (i in 0 until input.length step chunkSize) {
    val end = (i + chunkSize).coerceAtMost(input.length)
    chunks.add(input.substring(i, end))
}

assertEquals(chunks, listOf("Hel", "loW", "orl", "d"))

This approach uses a loop to create substrings of the desired size and adds them to a mutable list. It uses coerceAtMost() to handle the last chunk that may be smaller than n.

6. Conclusion

In this article, we learned how to split a string into chunks of a given size using the chunked() and windowed() functions provided by the Kotlin standard library.

These functions are versatile and can handle most use cases with minimal code. For more specialized needs, a manual approach is always an option.

As always, the source code for the examples is available over on GitHub.