Education
Software Development Executive - III
Last updated on Nov 12, 2024
Last updated on Nov 12, 2024
Handling lists and sublists in Kotlin can sometimes result in unexpected errors, particularly with the infamous "IndexOutOfBoundsException." This issue often arises when working with sublists, indices, and elements that are outside the list size or trying to perform structural changes. If you've encountered this error, don't worry—you’re not alone!
In this blog, we’ll explore the common pitfalls of using Kotlin’s sublist functionality, why this exception occurs, and how to avoid IndexOutOfBoundsException in your Kotlin code.
A Kotlin Sublist IndexOutOfBoundsException occurs when you try to access indices of a list that are beyond its bounds. This is particularly common when you use functions like subList, slice, or access elements with an invalid index. Let's break down how sublists work and common issues that may cause this error.
In Kotlin, the subList function allows you to create a view of a portion of an original list using specified indices. The syntax for subList is as follows:
1val list = listOf(1, 2, 3, 4, 5) 2val sublist = list.subList(fromIndex, toIndex)
Here, fromIndex is inclusive, while toIndex is exclusive. For example, if you want to get a sublist from index 2 to 4, you would write:
1val sublist = list.subList(2, 4) // Retrieves elements at indices 2 and 3 (4 is exclusive)
However, fromIndex and toIndex must be within the list size, or the function throws IndexOutOfBoundsException. Let's examine key errors to avoid when working with sublists.
One of the most common mistakes is providing indices that exceed the list size. For example, if your list has a size of 5 and you attempt to access a sublist using fromIndex or toIndex beyond this limit, the function throws IndexOutOfBoundsException.
1val list = listOf(1, 2, 3, 4, 5) 2val sublist = list.subList(4, 6) // Error: toIndex 6 is out of bounds
In this example, the toIndex of 6 is out of range for a list of size 5, resulting in an exception.
Fix: Always verify that both fromIndex and toIndex are within bounds. You can use list.size to validate this dynamically:
1if (fromIndex >= 0 && toIndex <= list.size) { 2 val sublist = list.subList(fromIndex, toIndex) 3}
A common misunderstanding is thinking that a sublist is independent of the original list. In reality, sublists are merely views of the original list. Any structural changes to the sublist (such as adding or removing elements) will impact the original list and vice versa.
1val list = mutableListOf(1, 2, 3, 4, 5) 2val sublist = list.subList(1, 4) 3sublist.add(6) // Throws UnsupportedOperationException
Here, sublist is a view of the original list, and since it’s immutable, attempting a structural change like add throws an exception.
Fix: If you need a modifiable version, consider creating a new list:
1val newList = list.subList(1, 4).toMutableList() 2newList.add(6) // Works without error
In Kotlin, both slice and subList can extract parts of a list, but they behave differently. slice is a safer option when dealing with invalid indices because it won’t throw an exception if you specify out-of-range indices.
1val list = listOf(1, 2, 3, 4, 5) 2val sliced = list.slice(1..3) // Returns [2, 3, 4]
The slice function accepts a range, which avoids IndexOutOfBoundsException. Unlike subList, slice is safer if you need only specific elements and may have uncertain indices.
If you make structural changes to the original list while iterating through a sublist, you’ll encounter unpredictable behavior and likely throw an exception. This happens because altering the original list affects the sublist’s bounds.
1val list = mutableListOf(1, 2, 3, 4, 5) 2val sublist = list.subList(1, 4) 3list.add(6) // Changes original list's structure 4println(sublist) // May throw View Undefined Exception
Fix: Avoid modifying the original list while working with its sublist or create a new list if necessary.
Using subList on an empty list or with invalid indices can lead to IndexOutOfBoundsException. If you need to handle cases where the sublist might be empty, use return emptyList() as a fallback.
1val list = listOf<Int>() 2val sublist = if (list.size >= 2) list.subList(0, 2) else emptyList()
This example uses return emptyList() when the list size is less than the required indices, avoiding exceptions.
Here are some practical examples to help you avoid IndexOutOfBoundsException while working with sublists:
Always check the list size before specifying indices in subList.
1val list = listOf(1, 2, 3, 4, 5) 2val fromIndex = 1 3val toIndex = 4 4 5if (fromIndex >= 0 && toIndex <= list.size) { 6 val sublist = list.subList(fromIndex, toIndex) 7 println(sublist) 8} else { 9 println("Invalid indices for sublist.") 10}
If you need to modify a sublist, convert it into a new list to prevent errors.
1val list = listOf(1, 2, 3, 4, 5) 2val mutableSublist = list.subList(1, 4).toMutableList() 3mutableSublist.add(6) // Safe modification
If you’re unsure about the indices, use slice to avoid IndexOutOfBoundsException.
1val list = listOf(1, 2, 3, 4, 5) 2val slicedList = list.slice(1..3) // Avoids out-of-bounds error
The Kotlin Sublist IndexOutOfBoundsException can be tricky to handle, especially if you’re unfamiliar with the pitfalls of using sublists. By ensuring your indices are within the list size, avoiding structural changes on sublists, and considering alternatives like the slice function, you can prevent this common error. Following these practices not only avoids frustrating exceptions but also keeps your code clean, predictable, and robust.
Tired of manually designing screens, coding on weekends, and technical debt? Let DhiWise handle it for you!
You can build an e-commerce store, healthcare app, portfolio, blogging website, social media or admin panel right away. Use our library of 40+ pre-built free templates to create your first application using DhiWise.