列表<列表<炭>&GT; + List <char> = List <any>?

时间:2018-03-30 08:11:16

标签: kotlin

我有一个有效的代码。

class ListManipulate(val list: List<Char>, val blockCount: Int) {

    val result: MutableList<List<Char>> = mutableListOf()

    fun permute(sequence: List<Int> = emptyList(), start: Int = 0, count: Int = blockCount) {
        if (count == 0) {
            result.add(constructSequence(sequence))
            return
        }
        for (i in start .. list.size - count) {
            permute(sequence + i, i + 1, count - 1)
        }
    }

    private fun constructSequence(sequence: List<Int>): List<Char> {
        var result = emptyList<Char>()
        for (i in sequence) {
            result += list[i]
        }
        return result
    }
}

然而,当我将result从MutableList更改为普通List时,即

    var result: List<List<Char>> = emptyList()
    // ...
            result += constructSequence(sequence)

我收到此错误Type mismatch. Require: List<List<Char>>; Found: List<Any>

完整代码如下

class ListManipulate(val list: List<Char>, val blockCount: Int) {

    var result: List<List<Char>> = emptyList()

    fun permute(sequence: List<Int> = emptyList(), start: Int = 0, count: Int = blockCount) {
        if (count == 0) {
            result += constructSequence(sequence)
            return
        }
        for (i in start .. list.size - count) {
            permute(sequence + i, i + 1, count - 1)
        }
    }

    private fun constructSequence(sequence: List<Int>): List<Char> {
        var result = emptyList<Char>()
        for (i in sequence) {
            result += list[i]
        }
        return result
    }
}

为什么result + constructSequence(sequence)会导致List<Any>而不是List<List<Char>>

有没有办法我仍然可以使用普通的List&gt;而不是可变列表?

2 个答案:

答案 0 :(得分:2)

CTRL +点击IDEA中的+,您会看到它带您进入以下功能:

/**
 * Returns a list containing all elements of the original collection and then all elements of the given [elements] collection.
 */
public operator fun <T> Collection<T>.plus(elements: Iterable<T>): List<T> {
    /* ... */
}

这意味着您将elements的所有单个元素添加到接收器。也就是说,您将所有T添加到List<List<T>>。由于List<T>不是T,因此您将获得List<Any>

答案 1 :(得分:0)

问题在于+=overloaded。如果它看到IterableArraySequence,则表现不同。您必须明确使用plusElement()来实现您想要的行为。

请考虑以下代码:

class ListManipulate(val list: List<Char>, val blockCount: Int) {

    var result: List<List<Char>> = emptyList()

    fun permute(sequence: List<Int> = emptyList(), start: Int = 0, count: Int = blockCount) {
        if (count == 0) {
            result = result.plusElement(constructSequence(sequence))
            return
        }
        for (i in start..list.size - count) {
            permute(sequence + i, i + 1, count - 1)
        }
    }

    private fun constructSequence(sequence: List<Int>): List<Char> =
        List(sequence.size, { i -> list[sequence[i]] })
}

PS:我也冒昧地将你的constructSequence()更新为更简洁的内容。

顺便说一句:+=在内部使用addAll

/**
 * Returns a list containing all elements of the original collection and then all elements of the given [elements] collection.
 */
public operator fun <T> Collection<T>.plus(elements: Iterable<T>): List<T> {
    if (elements is Collection) {
        val result = ArrayList<T>(this.size + elements.size)
        result.addAll(this)
        result.addAll(elements)
        return result
    } else {
        val result = ArrayList<T>(this)
        result.addAll(elements)
        return result
    }
}

旁注:你也可以这样做:

 result.toMutableList().add(constructSequence(sequence))

返回MutableList很好,唯一的区别是List接口没有操作方法。在内部,两者都由ArrayList

表示
@SinceKotlin("1.1")
@kotlin.internal.InlineOnly
public inline fun <T> List(size: Int, init: (index: Int) -> T): List<T> = MutableList(size, init)