Why is call to put() failing to compile in Kotlin when it compiles in Java with similar code

Viewed 141

I have the following function in java and I need to convert it to Kotlin.

@Override
public void afterTextChanged(Editable s) {

    if (s != null && !"".equals(s.toString())) {
        int position = (Integer) mHolder.numEdit.getTag();
        // Saved to the data variable when the data changes
        mData.get(position).put("list_item_inputvalue",
                s.toString());
    }
}

This is the equivalent Kotlin code that I've created:

override fun afterTextChanged(s: Editable?) {

    if (s != null && "" != s.toString()) {
        val position = mHolder.numEdit!!.tag as Int
        // Saved to the data variable when the data changes
        mData?.get(position).put("list_item_inputvalue", s.toString())
    }
}

The compiler doesn't like the call to .put(). The variable mData in Java is:

private List<Map<String, String>> mData;

and Kotlin:

var mData: List<Map<String, String>>? = null

Why doesn't the compiler like the conversion of put in Kotlin?

UPDATE:

println(mData) = [{list_item_inputvalue=0}, {list_item_inputvalue=1},...]

println(mData?.get(position)) = {list_item_inputvalue=8}

error

Code in Java

2 Answers

Your problem centers around this statement in your question:

var mData: List<Map<String, String>>? = null

In Kotlin, the Map type is immutable, and so has no .put() method. That's the problem you're running up against. To fix it, just change this statement to:

var mData: List<MutableMap<String, String>>? = null

A second '?' is necessary after mData?.get(position) because that statement will return null if mData == null. That is, that statement returns a type of MutableMap<String, String>? even though the .put() by itself would return a type of MutableMap<String, String>.

To summarize...if you create a list of mutable maps, the compiler will then be happy with the statement:

mData?.get(position)?.put("list_item_inputvalue", s.toString())

Initially, it wasn't clear what exactly the question was, so let's start with the various syntax elements in here:

  • !!: the not-null assertion operator (!!) converts any value to a non-null type and throws an exception if the value is null. We can write b!!, and this will return a non-null value of b (e.g., a String in our example) or throw an NPE if b is null (quoted from kotlinlang)
  • [position]: Square brackets are translated to calls to get and set with appropriate numbers of arguments. (again, from kotlinlang) In other words: that is simply "syntactic" sugar: you can treat a collection (probably a list) as an array. Meaning: instead of writing down get(index) to denote an element in a list, you can just go [index] as if that were an ordinary array.

Kotlin allows to use someMap[someKey] for its own maps. So, to answer the initial question, a further "conversion" could replace the call to put() via square brackets as well.

In that case, you have to be aware of the fact that Kotlin maps are immutable by default (so when using mapOf() you get a immutable map). Or, if you want to have a mutable Kotlin map "around" a Java map, you have to use mutableMapOf()!

Related