我正在关注Scala视频教程,他提到前置::
占用一定的时间并随着列表长度追加:+
时间增加。并且,他也提到大部分时间颠倒列表前置和重新反转列表提供比附加更好的性能。
问题1
为什么前置::
需要不变的时间并且随着列表的长度追加:+
时间增加?
但是在教程中没有提到原因,我在谷歌尝试过。我找不到答案,但我找到了另一个surprising thing。
问题2
ListBuffer为append和prepend都需要恒定的时间。如果可能,为什么它没有在List中实现?
显然背后有理由!感谢有人能解释。
答案 0 :(得分:1)
答案1:
列表实现为链接列表。你持有的参考是它的头。
例如如果你有4个元素(1到4)的列表,它将是:
[1]->[2]->[3]->[4]->//
预先添加意味着向头部添加新元素并返回新头部:
[5]->[1]->[2]->[3]->[4]->//
对旧头[1]的引用仍然有效,从它的角度来看仍有4个元素 另一方面,添加元素到列表末尾添加含义。 由于List是不可变的,我们不能只将它添加到最后,但我们需要克隆整个List:
[1']->[2']->[3']->[4']->[5]->//
由于克隆意味着以相同的顺序复制整个列表,我们需要迭代每个元素并附加它。
答案2: ListBuffer是可变集合,更改它将改变所有引用。
答案 1 :(得分:0)
广告。 1. Scala中的列表被定义(简化)为头部和尾部。尾巴也是一个清单。向头部添加元素意味着创建一个带有新头部的新列表,并将现有列表作为新尾部。现有列表未更改。这就是为什么它是一个恒定的时间操作。 附加到列表需要重建现有列表,这不能在固定时间内完成。
广告。 2. ListBuffer是一个可变集合。在某些应用程序中它可能更有效,但另一方面,不可变集合是线程安全的并且易于扩展。