Why I'm getting "java.lang.IndexOutOfBoundsException: Index 0 out of bounds for length 0" while running next code??? :
val totalList = mutableListOf<MutableList<Int>>()
fun main() {
for (i in 0..15) {
for (j in 0..10) {
*some operations and calculations with **var element of type Int***
totalList[i].add(element)
}
}
}
I was thinking that in such case while iterating through 'j' it should add elements to mutableList[i], after this it should start adding elements to mutableList[i + 1] etc.... But instead I am recieving IndexOutOfBoundsException....
val totalList = mutableListOf<MutableList<Int>>()All this does is create one list which is going to contain
MutableList<Int>items. Right now, there's nothing in it (you've supplied no initial elements in the parentheses).Skip forward a bit, and you do this:
You're trying to get the first element of that empty list and
addto it. But there is no first element (index 0) because the list is empty (length 0). That's what the error is telling you.There's lots of ways to handle this - one thing you could do is create your lists up-front:
Or you could do it the way you are now, only using
getOrElseto generate the empty list on-demand, when you try togetit but it doesn't exist:Personally I don't really like this, you're using explicit indices but you're
adding new list items to the end of the main list. That implicity requires that you're iterating over the list items in order - which you are here, but there's nothing enforcing that. If the order ever changed, it would break.I'd prefer the first approach - create your structure of lists in advance, then iterate over those and fill them as necessary. Or you might want to consider arrays instead, since you have a fixed collection size you're "completing" by adding items to specific indices
Another approach (that I mentioned in the comments) is to create each list as a whole, complete thing, and then add that to your main list. This is generally how you do things in Kotlin - the standard library contains a lot of functional tools to allow you to chain operations together, transform things, and create immutable collections (which are safer and more explicit about whether they're meant to be changed or they're a fixed set of data).
(Or you could create the list directly with
List(11) { j -> ... }but this is a more general example of transforming a bunch of things to a bunch of other things)That example there is kinda half and half - you still have the imperative
forloop going on as well. Writing it all using the same approach, you can get:I'd probably prefer the
List(count) { i -> ... }approach for this, it's a better fit (this is a general example). That would also be better since you could useMutableListinstead ofList, if you really need them to be mutable (with themaps you could just chain.toMutableList()after the mapping function, as another step in the chain). Generally in Kotlin, collections are immutable by default, and this kind of approach is how you build them up without having to create a mutable list etc. and add items to it yourself