List 如何在Scala中复制列表

List 如何在Scala中复制列表,list,scala,copy,shallow-copy,List,Scala,Copy,Shallow Copy,我想在Scala中复制一个列表 我想做一些事情,比如: val myList = List("foo", "bar") val myListCopy = myList.clone 但是克隆方法受保护。要筛选列表: val list = List(1,2,3,4,5) //only evens val evens = list.filter(e=>e%2 == 0) println(list) //--> List(1, 2, 3, 4, 5) println(evens) /

我想在Scala中复制一个列表

我想做一些事情,比如:

val myList = List("foo", "bar")
val myListCopy = myList.clone
但是克隆方法受保护。

要筛选列表:

val list = List(1,2,3,4,5)
//only evens
val evens = list.filter(e=>e%2 == 0)

println(list)
//--> List(1, 2, 3, 4, 5)

println(evens) 
//--> List(2, 4)
您还可以使用通配符保存几个字符:

val evens = list.filter(_%2==0)

注意,如上所述,列表是不可变的。这意味着这些操作不会修改原始列表,而是实际创建一个新列表。

这里没有答案:不要这样做。
列表
是不可变的,因此复制一个列表绝对没有意义

让我们考虑一些操作:

val list = List(1,2,3)
val l1 = 0 :: list
val l2 = "a" :: list
l1
l2
都没有改变
list
,但它们都创建了引用
list
的新列表

让我们详细解释一下。构造函数
List(1,2,3)
正在创建三个元素,并使用单例对象。具体地说,它正在实例化这些元素:

::(3, Nil)
::(2, reference to the previous element)
::(1, reference to the previous element)
Nil
是一个单例对象。标识符
列表
实际指向的是最后一个元素

现在,当您将
0::list
分配给
l1
时,您正在实例化一个新对象:

::(0, reference to ::(1, etc))
当然,由于有一个对
列表的引用
,您可以将
l1
视为一个包含四个元素的列表(如果将
Nil
计算为五个元素)

现在
l2
甚至不属于同一类型的
列表
,但它也引用了它!在这里:

::("a", reference to ::(1, etc))
然而,所有这些对象的重要一点是它们不能被改变。没有任何setter,也没有任何方法会更改它们的任何属性。它们的“头”(我们称之为第一个元素)中永远有相同的值/引用,而“尾”(我们称之为第二个元素)中永远有相同的引用

但是,有些方法看起来像是在更改列表。不过,请放心,他们正在创建新的列表。例如:

val l3 = list map (n => n + 1)
方法映射创建一个大小相同的全新列表,其中新元素可以从
列表
中的对应元素计算出来(但您也可以忽略旧元素)

虽然
l4
的元素与
list
相同(但类型不同),但它也是一个全新的列表。方法
filter
根据您传递的规则创建一个新列表,告诉它哪些元素进入,哪些元素不进入。它不会尝试优化,以防返回现有列表

val l5 = list.tail
这不会创建新列表。相反,它只是将
l5
分配给
list
的现有元素

val l6 = list drop 2
同样,没有创建新列表

val l7 = list take 1
然而,这创建了一个新的列表,正是因为它不能更改
list
的第一个元素,使其尾部指向
Nil

以下是一些附加的实施细节:

  • List
    是一个抽象类。它有两个子类,类
    (是的,这是类的名称),和单例对象
    Nil
    <代码>列表是密封的,所以不能向其中添加新的子类,
    是最终的,所以不能对其进行子类化

  • 虽然您无法更改列表,但在某些操作中,它在内部使用可变状态。这有助于提高性能,但它是本地化的,因此您编写的任何程序都无法检测到它,也不会因此受到影响。无论其他函数如何处理列表,或者有多少线程同时使用列表,您都可以按自己的意愿传递列表


这难道不相关吗?为什么?列表对象是不可变的。我想在循环中从列表中删除一个元素(使用remove(A=>Boolean)方法)。(注意:我在2小时前启动了Scala:))当调用
myList.remove(s=>s startsWith“f”)
时,会在删除
foo
的位置创建一个新列表<代码>我的列表保持不变。正如亚历山大·阿扎罗夫(Alexander Azarov)已经说过的那样,列表在Scala中默认是不可变的。用户请求一种复制列表(根据示例,我想是字符串列表)的方法,您的答案是创建一个新列表,过滤整数列表中的奇数元素。为什么这个回答被认为是最好的答案?我遗漏了什么?当问题要求克隆时,您如何回答筛选相关列表?
val l7 = list take 1