Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala是如何处理列表的?_Scala - Fatal编程技术网

Scala是如何处理列表的?

Scala是如何处理列表的?,scala,Scala,在Java中进行不必要的收集通常被认为是一种不好的做法,因为它会消耗一些内存和CPU。Scala似乎非常有效,并鼓励使用不可变的数据结构 Scala是如何处理列表的?使用什么技术来实现这一点?虽然关于列表特别有效的说法是值得怀疑的,但它比为每个操作创建集合的完整副本要好得多,就像使用Java的标准集合一样 这是因为List和其他不可变集合不仅仅是带有返回副本的变异方法的可变集合,而且它们的设计与不可变性不同。他们利用了所谓的“结构性共享”。如果更改后集合的部分保持不变,则不需要复制这些部分,并且

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


Scala是如何处理列表的?使用什么技术来实现这一点?

虽然关于列表特别有效的说法是值得怀疑的,但它比为每个操作创建集合的完整副本要好得多,就像使用Java的标准集合一样

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

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

您有一个
列表(1,2,3)
,您想在0之前加上前缀

val original = List(1,2,3)
val updated = 0 :: original
您的列表将如下所示

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

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


其他类型的集合在不同的操作中更好。例如,Vector可以在摊销的固定时间内进行前置和追加,并且具有良好的随机访问和更新功能(尽管仍然比原始可变数组差得多)。在大多数情况下,在保持不变的情况下,它将比列表更有效。它的实现相当复杂。它使用trie数据结构,有许多内部数组来存储数据。未更改的内容可以共享,只有需要通过更新操作进行更改的内容才需要复制。

虽然评论是正确的,但认为列表特别有效的说法是可疑的,它比为每个操作执行集合的完整拷贝要好得多,就像您对Java的标准集合所做的那样

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

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

您有一个
列表(1,2,3)
,您想在0之前加上前缀

val original = List(1,2,3)
val updated = 0 :: original
您的列表将如下所示

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

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


其他类型的集合在不同的操作中更好。例如,Vector可以在摊销的固定时间内进行前置和追加,并且具有良好的随机访问和更新功能(尽管仍然比原始可变数组差得多)。在大多数情况下,在保持不变的情况下,它将比列表更有效。它的实现相当复杂。它使用trie数据结构,有许多内部数组来存储数据。未更改的列表可以共享,只有需要通过更新操作更改的列表才需要复制。

这种“Scala列表非常有效”的假设来自哪里?Scala鼓励用户使用不可变列表的事实并不意味着它们是有效的。Scala列表基本上是单链接列表。你在说什么样的效率?不可变数据结构的使用与效率关系不大,与可预测性关系更大。在Scala中,使用List并没有比Java效率更高的事情了。好吧,List prepend操作是有效的,但除此之外,其他操作必须涉及复制整个集合。就我而言,scala集合的效率类似于java流。(但为了让比较有意义,你必须使用懒惰的方法,比如scala Stream)你在说什么