Scala';s toList函数似乎很慢
我的印象是,对不可变的seq调用seq.toList()将创建一个新的列表,该列表共享第一个列表的结构状态。我们发现这可能非常缓慢,我不知道为什么。它只是共享结构状态,对吗?我不明白为什么它会在知道所有元素永远不会改变的情况下对它们进行n次复制。Scala中的Scala';s toList函数似乎很慢,scala,Scala,我的印象是,对不可变的seq调用seq.toList()将创建一个新的列表,该列表共享第一个列表的结构状态。我们发现这可能非常缓慢,我不知道为什么。它只是共享结构状态,对吗?我不明白为什么它会在知道所有元素永远不会改变的情况下对它们进行n次复制。Scala中的列表是一种特殊的数据结构:的实例::每个实例都包含一个值,然后在链的末尾加上Nil 如果toListaList,则需要O(1)时间。如果您在任何其他内容上列出,则必须将其转换为列表,其中涉及O(n)对象分配(所有:实例) 因此,您必须询问是
列表是一种特殊的数据结构:的实例::
每个实例都包含一个值,然后在链的末尾加上Nil
如果toList
aList
,则需要O(1)
时间。如果您在任何其他内容上列出,则必须将其转换为列表
,其中涉及O(n)
对象分配(所有:
实例)
因此,您必须询问是否确实需要一个scala.collection.immutable.List
。这就是toList
提供给您的信息。Scala中的列表是一种特殊的数据结构::
的实例,每个实例都包含一个值,然后在链的末尾加上Nil
如果toList
aList
,则需要O(1)
时间。如果您在任何其他内容上列出,则必须将其转换为列表
,其中涉及O(n)
对象分配(所有:
实例)
因此,您必须询问是否确实需要一个scala.collection.immutable.List
。这就是toList
提供给您的。共享结构状态对于特定数据结构上的特定操作是可能的
对于Scala中的列表数据结构,我的理解是每个元素都引用下一个元素,从头部到尾部,因此是一个单链接列表
从结构-状态共享的角度考虑,从内部数据结构的角度考虑这方面的限制。将一个元素添加到列表(X)的头部可以有效地创建一个新列表(X'),新元素作为X'的头部,旧列表(X)作为尾部。对于这个特定的操作,内部状态可以完全共享
以上相同的操作可用于创建一个新列表(X'),新元素作为X'的头部,X中的任何元素作为尾部,只要您接受尾部将是您从X中选择的元素,加上它的数据结构中已有的所有其他元素
从逻辑上考虑,每个数据结构都有一个内部结构,允许使用简单的共享内部结构执行某些操作,而其他操作需要更具侵入性和更昂贵的计算
从我的角度来看,这里的关键是理解内部数据结构本身对操作的约束
例如,考虑上面关于双链表数据结构的相同操作,您将看到有很大不同的限制。
就我个人而言,我发现了解内部结构有助于理解特定操作的后果
在对任意序列执行toList操作的情况下,由于不知道任意序列的内部数据结构,因此必须假设O(n)。List.toList具有作为列表的明显性能优势。对于特定数据结构上的特定操作,共享结构状态是可能的
对于Scala中的列表数据结构,我的理解是每个元素都引用下一个元素,从头部到尾部,因此是一个单链接列表
从结构-状态共享的角度考虑,从内部数据结构的角度考虑这方面的限制。将一个元素添加到列表(X)的头部可以有效地创建一个新列表(X'),新元素作为X'的头部,旧列表(X)作为尾部。对于这个特定的操作,内部状态可以完全共享
以上相同的操作可用于创建一个新列表(X'),新元素作为X'的头部,X中的任何元素作为尾部,只要您接受尾部将是您从X中选择的元素,加上它的数据结构中已有的所有其他元素
从逻辑上考虑,每个数据结构都有一个内部结构,允许使用简单的共享内部结构执行某些操作,而其他操作需要更具侵入性和更昂贵的计算
从我的角度来看,这里的关键是理解内部数据结构本身对操作的约束
例如,考虑上面关于双链表数据结构的相同操作,您将看到有很大不同的限制。
就我个人而言,我发现了解内部结构有助于理解特定操作的后果
在对任意序列执行toList操作的情况下,由于不知道任意序列的内部数据结构,因此必须假设O(n)。List.toList作为一个列表具有明显的性能优势。您能否指定它被归类为快速的标准是什么?因此我认为标准是它似乎比仅仅更新一个简单对象慢得多。我的同事在做这个简单的测试时,实际上是将它与JWrappers(使用隐式转换将seq转换为一个列表)进行比较。我的意思是——当我们运行超过一百万个项目时,不同的是toList函数的速度慢了一倍(jwrapper和隐式转换的时间是15秒,而toList的时间是30秒。我必须在这里遗漏一些东西。显示您的代码?我们只能猜测您的基准是什么。我们使用的是3r