Kotlin中List.subList和slice的区别

31

我最近意识到 Kotlin 中有两个非常相似的函数可用于获取 List 的一部分,但我不确定它们之间的区别:

关于 List.subList 的文档 表示:

返回列表中从指定 fromIndex (包括)到 toIndex (排除)之间的部分的视图。返回的列表由此列表支持,因此返回列表中的非结构性更改会反映在此列表中,反之亦然。

基础列表中的结构性更改会使视图的行为未定义。

有关 slice 的文档 则表示:

返回包含指定索引范围内索引处的元素的列表。

或者

返回包含指定索引处的元素的列表。

看起来主要区别是第一个函数返回列表的“一部分的视图”,以及是否反映非结构性更改?不过我不太确定这是什么意思。

我查看了 slice 函数的源代码:

public fun <T> List<T>.slice(indices: IntRange): List<T> {
    if (indices.isEmpty()) return listOf()
    return this.subList(indices.start, indices.endInclusive + 1).toList()
}

但它从subList函数返回一个列表。

有人能解释一下这两个函数的区别以及何时可能更倾向于使用其中之一吗?


您可以查看示例,其中提到了sublistslice之间的区别,还可以使用droptake功能来实现相同的效果。https://chetangupta.net/bbk7/ - Chetan Gupta
1个回答

75

List<T>.slice 函数中的关键是末尾的 .toList(),它将使用浅层元素复制创建一个新的List

总结如下:

  • .slice() 将使用子集的浅层复制创建一个新的List;如果原始列表包含对象,则在切片中更改对象内的值将被看到,但在原始列表中替换对象或标量将不会在切片中看到
  • .subList() 仅是原始List的视图,它将反映列表中对象/标量以及列表中对象内部值的更改

您可以在此处查看差异:https://pl.kotl.in/-JU8BDNZN

fun main() {
    val myList = mutableListOf(1, 2, 3, 4)
    val subList = myList.subList(1, 3)
    val sliceList = myList.slice(1..2)
    println(subList) // [2, 3]
    println(sliceList) // [2, 3]
    
    myList[1] = 5
    println(subList) // [5, 3]
    println(sliceList) // [2, 3]
}

6
使用切片时,请注意列表内容不会被复制,而是引用同一个对象。因此,如果您更改myList中的对象,则也会影响sliceList中的对象,因为它们是同一个对象。您可以在此处查看示例:https://pl.kotl.in/AFbm6dWXf - MEX

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接