Kotlin的列表缺少“添加”,“删除”,地图缺少“放置”等?


197

在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)
    }
}

我没有找到的错误add,并remove从我的列表功能

我将其强制转换为ArrayList,但在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可以完成的那样?


1
只是说明为什么不能做myList = null,然后再致电时添加不带!!。您可以通过lateinit在属性前面使用关键字来克服此问题,如下所示:lateinit var myList: List<Int>这样就不需要立即初始化列表,但是您可以向编译器保证在第一次使用列表之前将其初始化。这是一个更平滑的解决方案,但它给您作为开发人员的责任。
达尔文

Answers:


351

与许多语言不同,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() 应该也可以。


4
好的,写得很好的答案。尽管下面有我,但我还是选择您作为模型答案:)
Elye

6
如果立即初始化列表,则无需使该列表可为空。我编辑了您的答案。
基里尔·拉赫曼

37

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

  • 具有不可变(只读)列表的不可变变量:

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


  • 具有可变列表的不可变变量:

    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)


  • 具有不可变列表的可变变量:

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

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

    var users = emptyList<User>()
    • 注意:您可以添加*项目到列表:
      • users += anotherUser -*它创建新的ArrayList并将其分配给 users


  • 具有可变列表的可变变量:

    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

        错误:Kotlin:赋值运算符含糊不清:
        公共运算符fun Collection.plus(element:String):在kotlin.collections中定义的列表
        @InlineOnly公共内联运算符fun MutableCollection.plusAssign(element:String):在kotlin.collections中定义的单位


另请参阅:https : //kotlinlang.org/docs/reference/collections.html


9

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

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

要么

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

8

显然,默认的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如何只读集合提供更好的编码。


您使用的是正确的MutableList,但是使用进行初始化null将无效。在类型为的可为空的接收器上仅允许安全或非空声明的调用MutableList<Int>
fulvio

它对我有效,但没有发现错误。除非需要,我不需要初始化它doSomething
Elye

@Elye我知道这是一个古老的答案和问题,但是使用lateinit而不是使列表可以为空是解决此问题的正确方法。lateinit虽然不记得是否从Kotlin的一开始就添加了,但这绝对是当今使用它的解决方案:-)
Darwind,

5

在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) 
}



2

将变异限制在建造者之内

此处最重要的答案正确地说明了Kotlin List(只读)(注意:它是只读的,不是“不可变的”)和之间的区别MutableList

通常,应该努力使用只读列表,但是,可变性在构造时仍然经常有用,尤其是在处理具有非功能接口的第三方库时。对于无法使用替代构造技术的情况,例如listOf直接使用或应用功能性构造(例如fold或)reduce,简单的“构建器功能”构造(如下所示)会从临时可变的清单中很好地生成只读列表:

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")
}

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

更新:从Kotlin 1.3.70开始,buildList以上的确切功能以及类似物和都可在标准库中作为实验功能使用。参见https://blog.jetbrains.com/kotlin/2020/03/kotlin-1-3-70-released/buildSetbuildMap


感谢,并且在apply方法中与业务逻辑配合得很好,甚至在.appy {}中使用了anotherList.ForEach {add(foo)}
BENN1TH

1

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

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

1

一个listimmutable通过Default,你可以使用ArrayList来代替。像这样 :

 val orders = arrayListOf<String>()

那么您可以add/delete从以下项目中进行选择:

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

默认情况下ArrayList是,mutable因此您可以对其执行操作。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.