Scala如何使列表高效?

时间:2017-04-04 09:04:08

标签: scala

在Java中使用不必要的集合通常被认为是一种不好的做法,因为它占用了一些内存和CPU。 Scala似乎非常有效,并鼓励使用不可变数据结构。

Scala如何通过列表提高效率?使用了哪些技术来实现这一目标?

1 个答案:

答案 0 :(得分:2)

虽然评论是正确的,但列表特别有效的声明是可疑的,但它比为Java标准集合执行每个操作的集合的完整副本要好得多。

这样做的原因是List和其他不可变集合不仅仅是使用变异方法返回副本的可变集合,而是针对不变性而设计的不同。他们利用所谓的“结构共享”。如果更改后集合的某些部分保持不变,则不需要复制这些部分,并且可以跨多个集合共享同一对象。这是因为不变性,没有变化可以改变,所以分享是安全的。

想象一下最简单的例子,在列表前面。

你有一个List(1,2,3),你想要加上0

val original = List(1,2,3)
val updated = 0 :: original

你的名单会看起来像这样

updated original
    \       \
     0 - - - 1 - - - 2 - - - 3

所需要的只是创建一个新节点并将其指向原始列表的头部。没有什么需要复制。类似地,tail和drop操作只需要返回对相应节点的引用,不需要复制任何内容。这就是List对prepend和tail操作非常好的原因,因为即使它创建了一个“新”列表,它也不会进行任何复制。

其他列表操作确实需要一些数量的复制,但总是尽可能少。只要列表尾部的一部分不变,就不需要复制。例如,当连接列表时,需要复制第一个列表,但是它的尾部只能指向第二个列表的头部,因此根本不需要复制第二个列表。这就是为什么,当连接长短列表时,最好将较短的列表放在“左”,因为它是唯一需要复制的列表。

其他类型的集合在不同的操作中更好。例如,Vector可以以分摊的常量时间进行前置和附加,以及具有良好的随机访问和更新功能(尽管仍比原始可变数组差很多)。在大多数情况下,它仍然是不可变的,比List更有效。它的实现非常复杂。它使用trie数据结构,有许多内部数组来存储数据。可以共享未更改的那些,只需要复制需要通过更新操作更改的那些。