在Scala中执行不可变字节数组的最有效方法是什么?

Ala*_*ent 6 arrays byte scala immutability

我想从某个地方获取一个字节数组(Array [Byte])(从文件中读取,从socket中读取等),然后提供一种有效的方法来从中提取位(例如,提供一个提取32位整数的函数)来自阵列中的偏移量N).然后我想包装字节数组(隐藏它),提供从数组中拉出位的函数(可能使用lazy val为每个位拉出).

我想有一个包装类,它在构造函数中采用不可变的字节数组类型来证明数组内容永远不会被修改.IndexedSeq [Byte]似乎相关,但我无法弄清楚如何从Array [Byte]转到IndexedSeq [Byte].

问题的第2部分是,如果我使用IndexedSeq [Byte],结果代码会变慢吗?我需要代码尽可能快地执行,因此如果编译器可以更好地使用它,那么就会坚持使用Array [Byte].

我可以在数组周围编写一个包装类,但这样会减慢速度 - 每次访问数组中的字节时都会有一个额外的间接级别.由于需要的阵列访问次数,性能至关重要.我需要快速代码,但希望能够很好地同时执行代码.谢谢!

PS:我是斯卡拉新手.

ret*_*nym 15

治疗Array[T]作为一种IndexedSeq[T]很难简化:

Array(1: Byte): IndexedSeq[Byte] // trigger an Implicit View
wrapByteArray(Array(1: Byte))    // explicitly calling
Run Code Online (Sandbox Code Playgroud)

拆箱会在额外的间接层之前很久就会杀了你.

C:\>scala -Xprint:erasure -e "{val a = Array(1: Byte); val b1: Byte = a(0); val
b2 = (a: IndexedSeq[Byte])(0)}"
[[syntax trees at end of erasure]]// Scala source: scalacmd5680604016099242427.s
cala

val a: Array[Byte] = scala.Array.apply((1: Byte), scala.this.Predef.
wrapByteArray(Array[Byte]{}));
val b1: Byte = a.apply(0);
val b2: Byte = scala.Byte.unbox((scala.this.Predef.wrapByteArray(a): IndexedSeq).apply(0));
Run Code Online (Sandbox Code Playgroud)

为了避免这种情况,Scala集合库应该专门针对元素类型,与Tuple1and的样式相同Tuple2.我被告知这是有计划的,但它涉及到比简单地@specialized在任何地方拍打更多,所以我不知道需要多长时间.

UPDATE

是的,WrappedArray是可变的,虽然collection.IndexedSeq[Byte]没有变异的方法,所以你可以只信任客户端不要转换为可变接口.Scalaz的下一个版本将包含ImmutableArray,它可以防止这种情况发生.

拳击通过这种通用方法从集合中检索元素:

trait SeqLike[+A, +Repr] extends IterableLike[A, Repr] { self =>
  def apply(idx: Int): A
}
Run Code Online (Sandbox Code Playgroud)

在JVM级别,此签名被类型擦除为:

  def apply(idx: Int): Object
Run Code Online (Sandbox Code Playgroud)

如果您的集合包含原语,也就是亚型AnyVal从该方法返回,就必须在相应的包装装箱.对于某些应用程序,这是一个主要的性能问题.整个库都是用Java编写的,以避免这种情况,特别是fastutils.

向Scala 2.8添加了注释定向特化,以指示编译器生成针对基本类型的排列定制的各种版本的类或方法.这已经被应用到一些地方已经在标准库,例如TupleN,ProductN,Function{0, 1, 2}.如果这也应用于集合层次结构,则可以减轻此性能成本.


oll*_*erg 10

如果您想在Scala中使用序列,我建议您选择以下其中一个:

不可变的seqs:

(链接的seqs)List,Stream,Queue

(索引seqs)矢量

可变序列:

(链接seq)ListBuffer

(索引seq)ArrayBuffer

新的(2.8)Scala集合对我来说很难掌握,主要是由于(正确的)文档的不足,还因为源代码(复杂的层次结构).为了清楚我的想法,我将这张照片想象成基本结构:

alt text http://www.programmera.net/scala/img/seq_tree.png

另外,请注意,Array它不是树结构的一部分,它是一种特殊情况,因为它包装了Java数组(这是Java中的一个特例).

  • 在Scala 2.8中,它的`Array`是Java的数组,因为Scala的`String`是Java的`String`:同一个,没有包装.有一些包含相应隐式转换的包装器,允许Scala的HOF用于序列与这些"借用"类型一起使用,但基本的`Array`(和`String`)是Java实体. (3认同)