Search code examples
androidkotlinpojo

Kotlin plus() not changing the original List


TL,DR

I have a Kotlin code where elements are added to arraylist but the list is not storing the new value although the return for the function shows the changed list.

Example problem: 
/* someList = ["A", "ab"] */
val x = someList.plus("Abc")

Example output: 
someList = ["A", "ab"] , x = ["A", "ab", "Abc"]

Full Problem

My code:

class FriendClass{
   /* others */
   @JsonProperty("messages")
   var messages: List<String>? = ArrayList()
}
class DataClass{
   /* singleton */
   /* others */
   @JsonProperty("friend_detail_list")
   var friendDetailList: List<FriendClass> = ArrayList()
}
class Adapter{
    val a = DataClass.getInstance().friendDetailList[0].messages?.plusElement("Hello")
    val b = DataClass.getInstance().friendDetailList[0].messages    
    val c = DataClass.getInstance().friendDetailList[0].messages?.toMutableList().add("Hello")
    val d = DataClass.getInstance().friendDetailList[0].messages 
    /* printing a, b, c, d */
}

My output:

messages already had ["a", "bcd", "xfd"] Now after printing the results are:

a = ["a", "bcd", "xfd", "Hello"]
b = ["a", "bcd", "xfd"] 
a = true
b = ["a", "bcd", "xfd"] 

How dow I make the original messages update it's values in the FriendClass?


Solution

  • Check the signature of the function:

    @kotlin.internal.InlineOnly
    public inline fun <T> Iterable<T>.plusElement(element: T): List<T> {
        return plus(element)
    }
    
    /**
     * Returns a list containing all elements of the original collection and then the given [element].
     */
    public operator fun <T> Collection<T>.plus(element: T): List<T> {
        val result = ArrayList<T>(size + 1)
        result.addAll(this)
        result.add(element)
        return result
    }
    

    It's clear from this that it doesn't modify the original list. What you want instead is probably:

    val messages = DataClass.getInstance().friendDetailList[0].messages
    DataClass.getInstance().friendDetailList[0].messages = messages.plusElement("Hello")
    

    This will work because messages is mutable (declared with var).

    There's a great article about some of these gotchas here.