在scala中进行函数编程时,在递归中使用数组是否有效



如果采用函数方法,这是最有效的方法吗?

@tailrec
def readLine(in: SomeTypeOfBuffer, a: Array[Byte]): Array[Byte] = {
val char = in.readByte()
char match{
case 'n'  => a 
case other => readLine(in, a :+ other) 
}
}

由于每个递归调用都会生成一个新的数组,因此必须对内存进行另一次调用,为另一个数组分配空间,并从内存中释放前一个数组。

这只是函数式编程的价格吗?

(我对scala和函数还比较陌生,所以如果我出了可怕的问题,请不要把我钉在十字架上(

正如@DeFuncT所说,最好使用(不可变(列表,因为它在构建时不会复制数据。我会教你怎么做。

我还将应用@QuickSilver的建议。

def readLine(in: SomeTypeOfBuffer): List[Byte] = {
val NewLine: Byte = 'n'.toByte
@annotation.tailrec
def loop(acc: List[Byte]): List[Byte]
in.readByte() match {
case NewLine => acc.reverse
case char    => loop(other :: acc)
}
loop(acc = List.empty)
}

附言:在常见的Scala中,您永远不会看到数组。也许是新的ArraySeqVector
普通数组通常只用于性能原因,并且通常包含在单个方法的范围内。

使用内部可变性来提高效率并提供安全的不可变API:没有错

@tailrec
private def readLineInner(in: DataInputStream, a: ArrayBuffer[Byte]): Array[Byte] = {
val char = in.readByte()
char match{
case 'n'  => a.toArray
case other => {
a.addOne(other)
readLineInner(in, a )
}
}
}
def readLine(in: DataInputStream): Array[Byte] =
readLineInner(in, new ArrayBuffer[Byte]())

在您的情况下最好使用List,因为List内部基本上是一个链表,而链表中的前缀是O(1(

编辑:更新为准备

最新更新