ループ内のIndexedSeqを構築するにはArrayBufferを使用し、続いて ".toVector()"を使用してVectorに変換する必要があります。Scala:IndexedSeq.newBuilderとArrayBuffer
プロファイリングされた例では、このセクションにCPUホットスポットがあることを示していました。代わりに、IndexedSeq.newBuilder()を使用し、続いて ".result()"で不変に変換しました。
この変更により、パフォーマンスが大幅に向上しました。コードはほとんど同じです。したがって、IndexedSeq.newBuilder()を使用するのがベストプラクティスであるようです。これは正しいです?以下の例のメソッドは、ArrayBufferの違いをコメントアウトして示しています。
def interleave[T](a: IndexedSeq[T], b: IndexedSeq[T]): IndexedSeq[T] = {
val al = a.length
val bl = b.length
val buffer = IndexedSeq.newBuilder[T]
//---> val buffer = new ArrayBuffer[T](al + bl)
val commonLength = Math.min(al, bl)
val aExtra = al - commonLength
val bExtra = bl - commonLength
var i = 0
while (i < commonLength) {
buffer += a(i)
buffer += b(i)
i += 1
}
if (aExtra > 0) {
while (i < al) {
buffer += a(i)
i += 1
}
} else if (bExtra > 0) {
while (i < bl) {
buffer += b(i)
i += 1
}
}
buffer.result()
//---> buffer.toVector()
}
「ArrayBuffer」自体を返さないのはなぜですか? 'IndexedSeq'を実装しています。 –
@AlexeyRomanov 'ArrayBuffer'は_mutable_' IndexedSeq'を実装しています。_OP_は_immutable_バージョンを返すようです。 –
'scala.collection.IndexedSeq'を返すと、(キャストやパターンマッチングなしで)それを変更することはできません。その敵対的なコードやひどく書かれたコードでは安全ではありませんが、これは重要な問題ではありません。 –