Kotlin's List missing "add" remove"; Map missing "put"等等?

在Java中,我们可以这样做

public class TempClass {
List<Integer> myList = null;
void doSomething() {
myList = new ArrayList<>();
myList.add(10);
myList.remove(10);
}
}

但如果我们直接重写给Kotlin,如下所示

class TempClass {
var myList: List<Int>? = null
fun doSomething() {
myList = ArrayList<Int>()
myList!!.add(10)
myList!!.remove(10)
}
}

我得到的错误,没有找到addremove函数从我的列表

我把它强制转换为数组列表,但强制转换是奇怪的,而在Java中,强制转换是不需要的。这就违背了使用抽象类List的目的

class TempClass {
var myList: List<Int>? = null
fun doSomething() {
myList = ArrayList<Int>()
(myList!! as ArrayList).add(10)
(myList!! as ArrayList).remove(10)
}
}

是否有一种方法可以让我使用List但不需要强制转换,就像在Java中可以做的那样?

167870 次浏览
显然,Kotlin的默认列表是不可变的。 要有一个可以更改的列表,应该使用MutableList,如下所示

class TempClass {
var myList: MutableList<Int>? = null
fun doSomething() {
myList = ArrayList<Int>()
myList!!.add(10)
myList!!.remove(10)
}
}

<强>更新 尽管如此,不建议使用MutableList,除非您确实想要更改列表。关于只读集合如何提供更好的编码,参考https://hackernoon.com/read-only-collection-in-kotlin-leads-to-better-coding-40cdfa4c6359

与许多语言不同,Kotlin区分了可变和不可变集合(列表、集、映射等)。精确控制何时可以编辑集合对于消除错误和设计好的api很有用。

https://kotlinlang.org/docs/reference/collections.html

你需要使用MutableList列表。

class TempClass {
var myList: MutableList<Int> = mutableListOf<Int>()
fun doSomething() {
// myList = ArrayList<Int>() // initializer is redundant
myList.add(10)
myList.remove(10)
}
}

MutableList<Int> = arrayListOf()也应该工作。

在不可变数据的概念中,也许这是一个更好的方法:

class TempClass {
val list: List<Int> by lazy {
listOf<Int>()
}
fun doSomething() {
list += 10
list -= 10
}
}

https://kotlinlang.org/docs/reference/collections.html

根据上面的链接列表,>在Kotlin中是不可变的。 然而,这将工作:

var list2 = ArrayList<String>()
list2.removeAt(1)

在Kotlin中以不同的方式定义List集合:

  • < p > 带不可变(只读)列表的不可变变量:

    val users: List<User> = listOf( User("Tom", 32), User("John", 64) )
    


    < / p >

  • < p > 带可变列表的不可变变量:

    val users: MutableList<User> = mutableListOf( User("Tom", 32), User("John", 64) )
    

    或者没有初始值-空列表且没有显式变量类型:

    val users = mutableListOf<User>()
    //or
    val users = ArrayList<User>()
    
    • 你可以添加项目到列表:
      • users.add(anohterUser)
      • users += anotherUser(在引擎盖下它是users.add(anohterUser))
      • 李< / ul > < / > 李< / ul > < / >


      • < p > 可变变量与不可变列表:

        var users: List<User> = listOf( User("Tom", 32), User("John", 64) )
        

        或者没有初始值-空列表且没有显式变量类型:

        var users = emptyList<User>()
        
          注意:你可以在列表中添加*项:
          • users += anotherUser - *它创建一个新的数组列表并将其赋值给users
          • 李< / ul > < / > 李< / ul > < / >


          • < p > 可变变量与可变列表:

            var users: MutableList<User> = mutableListOf( User("Tom", 32), User("John", 64) )
            

            或者没有初始值-空列表且没有显式变量类型:

            var users = emptyList<User>().toMutableList()
            //or
            var users = ArrayList<User>()
            
              注意:您可以向列表中添加项目:
              • users.add(anohterUser)
              • 但没有使用users += anotherUser

                Error: Kotlin:赋值操作符歧义:
                公共运营商乐趣集合。plus(element: String): kotlin中定义的列表。集合
                @InlineOnly公共内联操作符fun MutableCollection。plusAssign(element: String): kotlin中定义的单元 李< /引用> < / > 李< / ul > < / > 李< / ul > < / >

              < p >
              参见: https://kotlinlang.org/docs/reference/collections.html < / p >

同意以上所有使用MutableList的答案,但你也可以从列表中添加/删除,并获得如下所示的新列表。

val newListWithElement = existingList + listOf(element)
val newListMinusElement = existingList - listOf(element)

val newListWithElement = existingList.plus(element)
val newListMinusElement = existingList.minus(element)

A listimmutable by Default,你可以用ArrayList代替。像这样:

 val orders = arrayListOf<String>()

那么你可以像下面这样add/delete项:

orders.add("Item 1")
orders.add("Item 2")

默认情况下,ArrayListmutable,所以你可以对它执行操作。

在Kotlin中,你必须使用MutableListArrayList

让我们看看MutableList的方法是如何工作的:

var listNumbers: MutableList<Int> = mutableListOf(10, 15, 20)
// Result: 10, 15, 20


listNumbers.add(1000)
// Result: 10, 15, 20, 1000


listNumbers.add(1, 250)
// Result: 10, 250, 15, 20, 1000


listNumbers.removeAt(0)
// Result: 250, 15, 20, 1000


listNumbers.remove(20)
// Result: 250, 15, 1000


for (i in listNumbers) {
println(i)
}

让我们看看ArrayList的方法是如何工作的:

var arrayNumbers: ArrayList<Int> = arrayListOf(1, 2, 3, 4, 5)
// Result: 1, 2, 3, 4, 5


arrayNumbers.add(20)
// Result: 1, 2, 3, 4, 5, 20


arrayNumbers.remove(1)
// Result: 2, 3, 4, 5, 20


arrayNumbers.clear()
// Result: Empty


for (j in arrayNumbers) {
println(j)
}

更新:从Kotlin 1.3.70开始,下面确切的buildList函数在标准库中作为实验函数可用,以及它的类似物buildSetbuildMap。看到https://blog.jetbrains.com/kotlin/2020/03/kotlin-1-3-70-released/

将可变性限制到构建器

上面的答案正确地说明了Kotlin中只读List(注:它是只读的,不是“不可变”的。)和MutableList之间的区别。

一般来说,应该尽量使用只读列表,然而,在建设时,可变性通常仍然有用,特别是在处理具有非函数接口的第三方库时。对于无法使用其他构造技术的情况,例如直接使用listOf,或应用像foldreduce这样的函数构造,一个简单的“构建器函数”;像下面这样的构造很好地从一个临时可变列表生成一个只读列表:

val readonlyList = mutableListOf<...>().apply {
// manipulate your list here using whatever logic you need
// the `apply` function sets `this` to the `MutableList`
add(foo1)
addAll(foos)
// etc.
}.toList()

这可以很好地封装到一个可重用的内联实用函数中:

inline fun <T> buildList(block: MutableList<T>.() -> Unit) =
mutableListOf<T>().apply(block).toList()

可以这样称呼:

val readonlyList = buildList<String> {
add("foo")
add("bar")
}

现在,所有的可变性都被隔离到一个用于构造只读列表的块范围中,其余代码使用从构建器输出的只读列表。

你可以像这样创建一个新的。

var list1 = ArrayList<Int>()
var list2  = list1.toMutableList()
list2.add(item)

现在你可以使用list2了,谢谢。