Scala:将元素追加到数组的最佳方法是什么?


111

说我有一个Array[Int]喜欢

val array = Array( 1, 2, 3 )

现在,我想将一个元素添加到数组,例如value 4,如以下示例所示:

val array2 = array + 4     // will not compile

我当然可以System.arraycopy()自己使用并执行此操作,但是必须为此有一个Scala库函数,而我根本找不到。感谢您的指导!

笔记:

  1. 我知道我可以追加另一个元素数组,如以下行所示,但这似乎太过复杂了:

    val array2b = array ++ Array( 4 )     // this works
  2. 我知道List vs Array的优缺点,出于各种原因,在这里我对扩展Array特别感兴趣。

编辑1

感谢您指出:+操作员方法的答案。这就是我想要的。不幸的是,它比使用自定义append()方法的实现arraycopy要慢得多-慢了大约2到3倍。查看中的实现SeqLike[],将创建一个构建器,然后向其添加数组,然后通过该构建器完成附加操作,然后呈现该构建器。数组不是一个好的实现。我比较了这两种方法进行了快速基准测试,查看了十个周期中最快的时间。对一个类的8元素数组实例进行1000万次单项重复Foo需要3.1秒的时间:+和1.7秒的简单时间,该append()方法使用System.arraycopy();在Long的8个元素的数组上执行1000万个单项追加重复,:+使用简单append()方法花费2.1秒,花费0.78秒。想知道是否无法使用的自定义实现在库中解决此问题Array

编辑2

对于它的价值,我提交了一张票:https : //issues.scala-lang.org/browse/SI-5017


11
为什么不使用ArrayBuffer及其+=方法?这将给您摊销O(1)追加。
Fred Foo

1
在斯卡拉,System.arraycopy(...)Array.copy(...)
范式

1
您知道List vs Array的优缺点,但对1000万个追加的基准测试结果感到惊讶吗?
用户未知,

您可以使用最后一次添加到数组(带有)ArrayBuffer后转换为的来再次运行基准测试吗?toArray
范式

@paradigmatic:基准当然不是将1000万个附加项添加到同一数组中,而是将1000万个单项重复项附加到8个元素数组中。我相应地更新了问题。
Gregor Scheidt

Answers:


204

您可以使用:+将元素追加到数组并+:在其前面添加:

0 +: array :+ 4

应该产生:

res3: Array[Int] = Array(0, 1, 2, 3, 4)

与的任何其他实现相同Seq


3
它与其他任何Scala 排序的集合相同,例如,它不适用于set(因为prepend和append并不意味着Set有任何意义)。
Nicolas

@Nicolas任何顺序。有序暗含排序
Daniel C. Sobral

@Daniel是的,我在写评论时只有一个小记忆孔,但没有找到明显的“顺序”一词
Nicolas

@tenshi所有这些运算符都会创建一个新数组吗?是的,它确实是这样(来自:+代码)Array.copy(repr, 0, result, 0, repr.length)
Timofey 2015年

59
val array2 = array :+ 4
//Array(1, 2, 3, 4)

作品也被“颠倒”:

val array2 = 4 +: array
Array(4, 1, 2, 3)

还有一个“就地”版本:

var array = Array( 1, 2, 3 )
array +:= 4
//Array(4, 1, 2, 3)
array :+= 0
//Array(4, 1, 2, 3, 0)

11
我只是想知道为什么Array集合不像ArrayBuffer那样使用append()方法。在我看来,它比使用新的运算符更协调和统一:+ / +:
Djvu 2014年

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.