Kotlin:val mutableList vs var immutableList。什么时候用哪个?

问题描述 投票:2回答:3

我们鼓励尽可能多地使用不可变变量。但是,如果我有时需要修改列表,我想知道我应该使用哪种方法......

  1. val mutableList = mutableListOf(),我可以在那里addremove相应

要么

  1. var immutableList = listOf()我会在每次更改时创建一个新列表(使用filter或+)。

我猜有一种不同的情景,一种比另一种更受欢迎。因此想知道何时应该使用其他等。

kotlin immutability mutable
3个回答
6
投票

可变和不可变列表增加了模型的设计清晰度。 这是为了迫使开发人员思考和澄清收集的目的。

  1. 如果集合将作为设计的一部分进行更改,请使用可变集合
  2. 如果model仅用于查看,请使用不可变列表

valvar的目的不同于不可变和可变列表。 valvar关键字谈论如何处理变量的值/引用。

  • var - 分配给变量的值/引用可以在任何时间点更改。
  • val - 值/引用只能为变量赋值一次,并且在执行后的某个时间点不能更改。

在Kotlin中将可变列表分配给val并向其添加元素是完全有效的。

val a = mutableListOf(1,2,3,4)
a.add(5)
println(a)

将输出

[1, 2, 3, 4, 5]

1
投票

val - >你可能认为你不能为变量重新分配。

//that is ok
var a:Int = 1
a=2
//Even you can reassign but you can't change its type
a= "string"  //that's wrong

//that is wrong
val b:Int = 1
b = 2

列表 - >你会认为你不能插入/删除/改变列表中的任何元素(不能对列表的内容做任何事情)

var list:List<Int> = listOf(1,2,3,4) //[1,2,3,4]
//you can read list
list.get(0)
list[0]
//but you can't change(/write) the content of the list (insert/delete/alter)
list.set(0, 100)
list.add(5)
list.removeAt(0)

var mutableList:MutableList<Int> = mutableListOf(1,2,3,4) //[1,2,3,4]
//you can read and write
mutableList.get(0)
mutableList.set(0, 100) //[100,2,3,4]
mutableList.add(5)      //[100,2,3,4,5]
mutableList.removeAt(0) //[2,3,4,5]

结合他们两个,你会得到四个案例

案例1:var mutableList:MutableList = mutableListOf(1,2,3,4)

//you can reassign 
mutableList = mutableListOf(4,5,6,7) //[4,5,6,7]
//you can alter the content 
mutableList.set(0, 100) //[100,5,6,7]
mutableList.add(8)      //[100,5,6,7,8]
mutableList.removeAt(0) //[5,6,7,8]

案例2:val mutableList:MutableList = mutableListOf(1,2,3,4)

//you can't reassign 
mutableList = mutableListOf(4,5,6,7) //that's wrong

//you can alter the content 
mutableList.set(0, 100) //[100,2,3,4]
mutableList.add(8)      //[100,2,3,4,8]
mutableList.removeAt(0) //[2,3,4,8]

案例3:var list:List = ListOf(1,2,3,4)

//you can reassign 
list= ListOf(4,5,6,7) //[4,5,6,7]

//you can't alter the content 
list.set(0, 100) //that's wrong
list.add(8)      //that's wrong
list.removeAt(0) //that's wrong

案例4:val列表:List = ListOf(1,2,3,4)

//you can't reassign 
list= ListOf(4,5,6,7) //that's wrong

//you can't alter the content 
list.set(0, 100) //that's wrong
list.add(8)      //that's wrong
list.removeAt(0) //that's wrong

//the only thing you can do is Read
list.get(0)  //return 1
list[0]      //return 1

0
投票

我猜有一种不同的情景,一种比另一种更受欢迎。因此想知道何时应该使用其他等。

有几个原因导致不可变对象通常更可取:

  • 他们鼓励函数式编程,其中state不会发生变异,而是传递给下一个基于它创建新状态的函数。这在Kotlin收集方法中非常明显,例如mapfilterreduce等。
  • 没有副作用的程序通常更容易理解和调试(您可以确定对象的值始终是其定义的值)。
  • 在多线程程序中,不可变资源不会导致竞争条件,因为不涉及写访问。

你也有一些缺点:

  • 仅仅为了添加/删除单个元素而复制整个集合在计算上是昂贵的。
  • 在某些情况下,当您繁琐地需要更改单个字段时,不变性会使代码更复杂。在Kotlin中,数据类带有内置的copy()方法,您可以在其中复制实例,同时仅为某些字段提供新值。

您最终使用哪一个取决于手头的用例。对于数据类(将一些属性捆绑在一起),坚持不变性通常是个好主意。对于集合,如果你使用不可变的只是为了修改它们的副本并重新分配指向它们的引用,你也可以使用可变的副本。如果您将应用程序的许多部分共享一个依赖于状态保持不变的集合,请使用不可变。

请记住,Kotlin系列有不同的概念:

  1. 可变集合:MutableList<T>, MutableSet<T>, MutableMap<T> 这些可以随时修改。
  2. 只读集合:List<T>, Set<T>, Map<T> 这些提供了集合的只读视图,即无法通过该引用修改集合。它不能保证不变性(对它的另一个可变引用仍然可以存在并用于修改)。
  3. (建议,尚未成为Kotlin的一部分) 不可变的收藏品:ImmutableList<T>, ImmutableSet<T>, ImmutableMap<T> 这些将保证真正的不变性,并提供基于它们构建新修改集合的模式。有关详细信息,请参阅Proposal
© www.soinside.com 2019 - 2024. All rights reserved.