0
votes

I'm using methods (for example the method containsKey of MutableList) that returns a true false. Since the function is written in java, Kotlin refers to return type as Boolean? and this the reason i'm getting a compilation error: "Required: Boolean, Found: Boolean?". I must say in some case (don't know why) using the method is ok and sometimes it return the error above. Can someone guess what is the reason?

My code:

val gamesPerCountriesMap = mutableMapOf<String,MutableMap<Long, List<AllScoresGameObj>>>()

if (countryName != null  && countryName != "" && !gamesPerCountriesMap.containsKey(countryName))
{
    gamesPerCountriesMap.put(countryName, mutableMapOf<Long,List<AllScoresGameObj>>())
}

if (!gamesPerCountriesMap.get(countryName)?.containsKey(competitionId))
{
    gamesPerCountriesMap.get(countryName)?.put(competitionId, listOf<AllScoresGameObj>())
}

First if is compiled the second one make the error:

Only safe (?.) or non-null asserted (!!.) calls are allowed on a nullable receiver of type Boolean?

if I remove the ! in the beginning of the second if i will different error:

Type mismatch: inferred type is Boolean? but Boolean was expected

After reading all the suggestion i wrote the following code:

gamesPerCountriesMap.get(countryName)?.let {
    if (!gamesPerCountriesMap.containsKey(it))
    {
        gamesPerCountriesMap.get(countryName)?.put(competitionId, listOf<AllScoresGameObj>())
    }
}

What do you think?

4
Show code snippetPrajwal Waingankar
Done two seconds ago :)Eitanos30
Error snippet, the code where u r getting this boolean error point that out as wellPrajwal Waingankar
Added two possible snippest errorsEitanos30
I found the solution, but i don't know why and how it solves the problem... If i adds a == false both error disappearsEitanos30

4 Answers

0
votes

You have to take care of the nullable

mutableMapOf<String?, MutableMap...

That means the keys can be a null String

If the countryName is a field, then

countryName?.let {
   //your validation here
}

Fields can be changed so compiler doesn't know if it nullable or not.

or

val safeName = countryName ?: return
0
votes

Basically in the Java, Boolean is an object type. It has 3 possible values: true, false, and null. Since kotlin have null safety feature, using ? in object type, like Boolean?, that's why it's asking you to make sure that the data isn't null. So for your code:

 if (!gamesPerCountriesMap.get(countryName)?.containsKey(competitionId))
                        {
                            gamesPerCountriesMap.get(countryName)?.put(competitionId, listOf<AllScoresGameObj>())
                        }

It checks if the get method returning null or not, if it's not, then it proceed to the next function containsKey. If it's null, then it's pass the if statement. For the non-null asserted, it's force the Boolean? data type into the Boolean. This can be use if you're sure that the data must not be null, else it'll break your program, because you're accessing function in a null data. So it depends on your choice, you can use ? or !! if you sure it's not null.

0
votes
if (!gamesPerCountriesMap.get(countryName)?.containsKey(competitionId))

will check if the item is true, false or null. The "if" statement requires true or false. This is why you see "Type mismatch: inferred type is Boolean? but Boolean was expected"

if (gamesPerCountriesMap.get(countryName) == null || !gamesPerCountriesMap.get(countryName)!!.containsKey(competitionId))

if the item is null, or if not null but also does not contain competitionID, then do this, so thats what you want to use.

Edit:

You also want to allow the map to contain a null value like this:

val gamesPerCountriesMap = mutableMapOf<String,MutableMap<Long, List<AllScoresGameObj>>?>()

the "?" at the end allows the nested MutableMap to be null.

0
votes

You can reduce it like:

if (!countryName.isNullOrEmpty()) {
    gamesPerCountriesMap.getOrPut(countryName) { mutableMapOf<Long,List<AllScoresGameObj>>() }
}

gamesPerCountriesMap[countryName]!!.getOrPut(competitionId) { listOf<AllScoresGameObj>() }