Scala 如何避免可变集合的意外突变?

Scala 如何避免可变集合的意外突变?,scala,Scala,所以,我写了一个代码来比较排序算法。我实现了几个ALG作为单独的类。这里有一些解释 class BubbleSort(input:ListBuffer[Int]){ ... } class InsertionSort(input:ListBuffer[Int]){ ... } 我首先从我的驱动程序对象创建一个名为input的列表。 接下来,我将其传递给BubbleSort和InsertionSort的新实例。 然后我调用一个函数sort,它对我在对象创建过程中传递的ListBuffer进行排

所以,我写了一个代码来比较排序算法。我实现了几个ALG作为单独的类。这里有一些解释

class BubbleSort(input:ListBuffer[Int]){
...
}

class InsertionSort(input:ListBuffer[Int]){
...
}
我首先从我的驱动程序对象创建一个名为
input
的列表。 接下来,我将其传递给
BubbleSort
InsertionSort
的新实例。 然后我调用一个函数
sort
,它对我在对象创建过程中传递的ListBuffer进行排序

val input = new ListBuffer[Int]

//Populated input here

val bs = new BubbleSort(input)
val is = new InsertionSort(input)
bs.sort
is.sort
我面临的问题是,当调用
is.sort
时,我在对象创建过程中传递的列表已经被排序。我想这是因为我先调用了
bs.sort
,但为什么它会影响另一个类中的列表

感谢您的帮助。如果您想要更多的代码片段,我很乐意与您分享。提前谢谢

编辑 作为临时修复,我没有只创建一个列表
input
,而是使用样板代码创建了两个列表,
bsinput
isinput
。然后将每个类传递给单独的类

val bsinput = new ListBuffer[Int]
val isinput = new ListBuffer[Int]

//Populated both arrays with the same data

val bs = new BubbleSort(bsinput)
val is = new InsertionSort(isinput)
bs.sort
is.sort
这解决了问题,但这是唯一的办法吗?有没有一种惯用的方法

编辑2
正如@LuisMiguelMejíaSuárez所说,这是一个参考问题。使用了
input.clone
,现在可以使用了。

您将两次引用传递给同一个可变集合
ListBuffer
。 这意味着您的两个排序算法将在同一个集合上工作,因此在第二次排序时,您的列表缓冲区将已经排序

为了避免意外突变,您只需在每次传递时创建一个防御副本:

val input1 = new ListBuffer[Int]

//Populated input here

val input2 = input1.clone

val bs = new BubbleSort(input1)
val is = new InsertionSort(input2)

问题是您使用的是可变数据结构。因此,由于两个类都接收相同的引用,并且它们(可能)进行了排序,那么在调用
bs.sort
之后,
input
将已经被排序。您可以创建集合的副本,以便在排序之前进行排序。或者,更好的是,不要变异(至少不要改变输入),而是返回一个新的排序集合。你是对的。它们确实在适当的位置排序。所以问题是scala发送了引用而不是副本。我没有传递
input
,而是传递了
input.clone
。Scala像一个魔术师一样工作,只是为了澄清,它永远不会传递副本,它会传递引用,就像Java一样。在Scala上,我们通常不担心这一点,因为我们更喜欢不变性。因此,共享引用从来都不是问题,对于集合来说,这比为每次调用复制整个集合更有意义。@LuisMiguelMejíaSuárez如果我将
输入作为
列表传递,那么我必须在
BubbleSort
中复制它(当然还有
插入排序
)进入一个
列表缓冲区
。因此,在一天结束时,创建的副本数量是相同的。那么,在这两种方式中,哪一种更适合scala方式呢?大多数人会认为,改变输入是“不好的”(正如您所看到的,这可能会导致意外的bug),因此我建议避免这种情况。这两种算法都可以只使用递归以函数方式编写。然而,斯卡拉不是一个纯粹的功能语言,它的能力之一(IMHO最好的一个)是它允许你使用你认为最好的风格。因此,另一种选择是在方法的局部范围上使用可变集合或带有
var
(后者更安全)的不可变集合。