Eunno An
Eunno An

Reputation: 23

kotling mutableMapOf<String, MutableSet<String>> error

val bucket = mutableMapOf<String, MutableSet<String>>()

I insert multiple keys in bucket. My logic is here

 for(temp in report_unique){
            val str = temp.split(" ")//str example = "a b"
            
            if(bucket.containsKey(str[0]))
                bucket[str[0]]?.add(str[1])
            else{
                val t = mutableSetOf<String>()
                bucket[str[0]]? = t // runtime error
                bucket[str[0]]?.add(str[1])
            }

I don`t know why the error occured, and want to know right answer. So Hard Kotlin null checking.

Upvotes: 0

Views: 316

Answers (1)

Joffrey
Joffrey

Reputation: 37710

EDIT: since you clarified in the comments with more information and your actual code doesn't use the problematic ?, the problem is a bit clearer:

ArrayIndexOutOfBoundsException: Index 0 out of bounds for length 0

This error tells you that you're trying to access index 0 in str, and it's out of bounds because str is of length 0 (it has 0 elements). By accessing index 0, you're assuming that str contains at least 1 element, but it's apparently not the case.

You should look at what temp contains. If temp == "", split will return an empty list, and you'll see this error.


Original answer

I think you're mistaken and you don't have a runtime error but a compile error. Trying your code on the Kotlin playground, I got the following compile error:

Unexpected tokens (use ';' to separate expressions on the same line)

This is because the syntax of bucket[str[0]]? = t is invalid, you have an extra ?. Let's break it down.

The basic function to insert into a map is put, as in map.put(key, value). On top of that, Kotlin provides a convenient set operator that allows you to use the square bracket syntax. So when you write map[key] = value, it's translated into map.set(key, value).

The syntax for this specific operator doesn't support any ? here, and it's not even necessary in your case anyway, as you could simply write:

bucket[str[0]] = t

The map is not null, and here you're not trying to use a null value, you're assigning a non-null value to a key in the map, so there is no need to use any safe operator (?).

Alternative code

Now that this is out of the way, note that you can the whole if with the help of computeIfAbsent:

for(temp in report_unique){
    val str = temp.split(" ")//str example = "a b"

    bucket.computeIfAbsent(str[0]) { mutableSetOf<String>() }.add(str[1])
}

You could even replace the whole thing by creating the bucket map directly using groupBy:

val bucket = report_unique.groupBy({ it.substringBefore(" ") }, { it.substringAfter(" ")})

Upvotes: 1

Related Questions