list - 如何在 Scala 中复制列表

标签 list scala copy shallow-copy

我想在 Scala 中浅复制一个列表。
我想做这样的事情:

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

最佳答案

这是一个非答案:不要那样做。一个 List是不可变的,所以复制一个绝对没有意义。

让我们考虑几个操作:

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是一个单例对象。什么标识符list实际上指向的是最后一个元素。

现在,当您分配 0 :: list 时至 l1 ,您正在实例化一个新对象:
::(0, reference to ::(1, etc))

当然,因为有对 list 的引用,你可以想到l1作为四个元素的列表(或五个,如果您计算 Nil )。

现在 l2甚至不是同一类型的 list ,但它也引用了它!这里:
::("a", reference to ::(1, etc))

但是,关于所有这些对象的重要一点是它们无法更改。没有 setter ,也没有任何方法可以改变它们的任何属性。它们的“头部”(这就是我们所说的第一个元素)中将永远具有相同的值/引用,并且它们的“尾部”(这就是我们所说的第二个元素)中具有相同的引用。

但是,有些方法看起来像是在更改列表。但是请放心,他们正在创建新列表。例如:
val l3 = list map (n => n + 1)

方法映射创建了一个全新的相同大小的列表,其中新元素可以从 list 中的相应元素计算出来。 (但您也可能会忽略旧元素)。
val l4 = l2 filter (n => n.isInstanceOf[Int])

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

这不会创建新列表。相反,它只是简单地分配给 l5 list 的现有元素.
val l6 = list drop 2

同样,没有创建新列表。
val l7 = list take 1

然而,这会创建一个新列表,正是因为它无法更改 list 的第一个元素。使其尾部指向 Nil .

下面是一些额外的实现细节:
  • List是一个抽象类。它有两个后代,类 :: (是的,这就是类的名称)和单例对象 Nil . List是密封的,所以你不能向它添加新的子类,而且 ::是最终的,所以你不能子类化它。
  • 虽然您无法更改列表,但它在某些操作中内部使用可变状态。这有助于提高性能,但它是本地化的,因此您编写的任何程序都无法检测到它,或遭受其后果。您可以随意传递列表,无论其他函数如何处理它们,或者有多少线程同时使用它们。
  • 关于list - 如何在 Scala 中复制列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1445629/

    相关文章:

    scala - 使IntelliJ IDEA了解SBT依赖关系

    excel - 将部分日期从字段 A 复制并替换到 B

    java - 如何从Java中的List中获取特定的列列表

    javascript - jQuery,将单个 xml 列表解析为多个无序列表

    scala - 多个特质 mixin 和 Actor 的问题

    java - 如何从 sbt 中发现定义类的库?

    C++ 将一个对象的值复制到另一个对象

    java - Files.copy 抛出 java.nio.file.NoSuchFileException 即使要复制的文件确实存在

    list - 如何将包含集合的元组列表转换为字典?

    java - 删除一个对象并在 TreeSet 中添加另一个对象