scala - array vs arrayseq

spy*_*ome 11 arrays scala

这是一个普遍的问题,但我想知道是否有人可以告诉我使用数组与arrayseq有什么好处.从我所看到的Array是scala对java Arrays的表示,并且在它的api中没有太多成员,而Arrayseq似乎包含更丰富的api.谢谢你的建议.

Rex*_*err 38

实际上有四种不同的类可供选择,以获得可变的类似数组的功能.

Array + ArrayOps
WrappedArray
ArraySeq
ArrayBuffer
Run Code Online (Sandbox Code Playgroud)

Array是一个普通的旧Java数组.它是迄今为止对基元数组进行低级访问的最佳方法.没有开销.此外,它可以像Scala集合一样,由于隐式转换ArrayOps,它抓取底层数组,应用适当的方法,并在适当的情况下返回一个新数组.但由于ArrayOps它并不专门用于原语,因此速度很慢(与装箱/拆箱一样慢).

WrappedArray是一个普通的旧Java数组,但包含在所有Scala的集合中.它和它之间的区别ArrayOpsWrappedArray返回另一个WrappedArray- 至少你没有必须ArrayOps为每个操作反复重新编写Java原始数组的开销.当您使用Java进行大量互操作并且需要传递普通的旧Java数组时,最好使用它,但在Scala端,您需要方便地操作它们.

ArraySeq将其数据存储在普通的旧Java数组中,但它不再存储基元数组; 一切都是一系列的对象.这意味着原语在路上被装箱.如果你想多次使用原语,这实际上很方便; 因为您已经存储了盒装副本,所以您只需要将它们取消装箱,而不是在每次通用操作中打包并取消装箱.

ArrayBuffer就像一个数组,但你可以添加和删除元素.如果你要一直走到哪里ArraySeq,为什么不能在你使用时更改灵活性?

  • 这应该是围绕集合的每个(和任何)scala 文档的一部分。+1 (2认同)

Kev*_*ght 8

Array是Java的直接表示Array,并在JVM上使用完全相同的字节码.

Array的优势在于它是JVM上唯一不进行类型擦除的集合类型,Arrays也能够直接保存基元而不需要装箱,这可以使它们在某些情况下非常快.

另外,你得到了Java混乱的数组协方差行为.(如果你将例如一个Array[Int]Java类传递给它,它可以被分配给一个类型的变量,Array[Object]然后它将ArrayStoreException尝试添加任何不是的东西int.)

ArraySeq现在很少使用它,它更像是Scala旧版本的历史工件,它对数组的处理方式不同.无论如何,看到你必须处理拳击,你几乎肯定会发现另一种集合类型更适合你的要求.

否则......阵列具有完全相同的API为ArraySeq,由于从隐式转换ArrayArrayOps.

除非您特别需要数组的唯一属性,否则请尽量避免使用它们.请参阅19:30左右的本演讲本文,了解Arrays可以引入的各种问题.

观看该视频后,有趣的是Scala Seq用于varargs :)


Vas*_*iuk 7

来自scala-lang.org论坛:

Array [T] - 优点:Native,fast - 限制:很少有方法(只有apply,update,length),需要在编译时知道T,因为Java字节码表示(char []不同于int []不同于Object [ ])

ArraySeq [T](以前称为GenericArray [T]的类): - 好处:仍然由本机数组支持,在编译时不需要知道任何关于T的东西(新的ArraySeq [T]"只是工作",即使没有人知道T),全套SeqLike方法,Seq [T]的子类型 - 限制:它由Array [AnyRef]支持,无论T是什么(如果T是原始的,那么元素将被装箱/在进出支持阵列的路上取消装箱)


处理基元时,ArraySeq [Any]Array [Any]快得多 .在任何代码中你都有Array [T],其中T不是<:AnyRef,你将获得更快的ArraySeq性能.

  • @Jim - 不,Vasil说得对(大多数情况下).`ArraySeq`在中途输入基元,并存储盒装基元.`Array`必须在每个元素访问时执行.因此,`Array`(通过`ArrayOps`进行隐式转换)就像是盒装基元的视图,而`ArraySeq`是强制的.如果你不到一次通过数组,'Array`会更好.如果你不止一次,'ArraySeq`会更好. (4认同)
  • 你确实有这种反向 - 正如你的引用所说,ArraySeq框和unboxes原语. (2认同)