Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Kotlin: java.lang.UnsupportedOperationException in MutableList add element

I'm implementing a stack algorithm for study purpose in Kotlin

class Stack<T:Comparable<T>>(list:MutableList<T>) {

    var items: MutableList<T> = list


    fun isEmpty():Boolean = this.items.isEmpty()

    fun count():Int = this.items.count()

    fun push(element:T) {
        val position = this.count()
        this.items.add(position, element)
    }

    override  fun toString() = this.items.toString()

    fun pop():T? {
        if (this.isEmpty()) {
            return null
        } else {
            val item =  this.items.count() - 1
            return this.items.removeAt(item)
        }
    }

    fun peek():T? {
        if (isEmpty()) {
            return null
        } else {
            return this.items[this.items.count() - 1]
        }
    }

}

And I'm trying to execute using this code:

fun main(args: Array<String>) {

        var initialValue = listOf<Int>(10) as MutableList<Int>
        var stack = Stack<Int>(initialValue)
          stack.push(22)
        println(stack.count())
        println(stack.isEmpty())
        println(stack.pop())
        println(stack.count())
        println(stack.isEmpty())

    }

When I run the code I receive this error:

Exception in thread "main" java.lang.UnsupportedOperationException
at java.util.AbstractList.add(AbstractList.java:148)
at Stack.push(Stack.kt:17)
at StackKt.main(Stack.kt:45)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)

This is related with the follow line that is implemented in push(element:T) method:

 this.items.add(position, element)

The most weird thing is that I used a very similar code implementing a orderedArray and it works perfectly.

Do you have any idea of what I'm doing wrong ?

like image 485
Sebastian Avatar asked Apr 05 '16 01:04

Sebastian


1 Answers

listOf<Int> is not truly mutable. According to the doc:

fun <T> listOf(vararg elements: T): List<T> (source) Returns a new read-only list of given elements. The returned list is serializable (JVM).

You should use mutableListOf<> instead.

The reason why as MutableList is permitted here is because listOf(10) returns Collections.singletonList(10) which returns a java.util.List (which Kotlin assumes implements the kotlin.collections.MutableList interface). So the compiler does not know it's not really mutable until the mutating method is called at runtime and throws the exception.

like image 110
szym Avatar answered Sep 28 '22 08:09

szym