Kotlin:val mutableList与var immutableList。什么时候使用?

时间:2018-08-07 03:04:15

标签: kotlin immutability mutable

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

  1. val mutableList = mutableListOf(),我可以addremove相应地

  1. var immutableList = listOf(),每次进行更改时,我都会在其中创建一个新列表(使用过滤器或+)。

我猜有几种不同的方案,一种是优先于另一种的。因此,我们想知道什么时候应该使用另一个,等等。

3 个答案:

答案 0 :(得分:6)

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

  1. 如果集合将在设计中更改,请使用可变集合
  2. 如果模型仅用于查看,请使用不可变列表

valvar的用途不同于不可变和可变的列表。
val var 关键字讨论了关键字的值/引用如何变量应予以处理。

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

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

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

将输出

[1, 2, 3, 4, 5]

答案 1 :(得分: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 wrng

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

ListOf->您可能认为您不能在列表中插入/删除/更改任何元素   (对列表的内容无能为力)

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]

SO 结合它们,您将得到四种情况

  

案例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: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

答案 2 :(得分:0)

  

我猜有几种不同的方案,一种是优先于另一种的。因此,我们想知道什么时候应该使用另一个,等等。

不可变对象通常是首选的几个原因:

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

您也有一些缺点:

  • 仅复制整个集合以添加/删除单个元素在计算上是昂贵的。
  • 在某些情况下,当您烦琐地需要更改单个字段时,不变性会使代码变得更加复杂。在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