主張
タイトル通り。Scalaの ArrayBuffer
では init
だけでなく dropRightInPlace
を使うことも検討してみませんか?元の ArrayBuffer
のデータを使わないという条件は付きますが dropRightInPlace
の方が高速です。
val filled = ArrayBuffer.fill(1000000)(1) assert(filled.init.length == 999999)
val filled = ArrayBuffer.fill(1000000)(1) assert(filled.dropRightInPlace(1).length == 999999)
蛇足
Scalaを触っていると、List
では ::
、他のコレクションでも +:
, :+
を使うことが多いです。その影響もあって head
に対して tail
, init
に対して last
を意識することも多いと思います。
そんなノリで foldLeft
中で ArrayBuffer
から init
を使っていたら、動かしてみたときになぜか遅くて頭を抱えてしまいました。
不思議に思っていたところ init
がcopyを作成していることに気が付きました。気付いてしまえば当然ですよね。
Rust言語の Vec
の pop
のように最後の要素をmutableに削除すればcopyを作成せずに高速に動作するはずなのですが、pop
なんてmethodは見当たりませんでした。
頭を捻っていたところ、それっぽいmethodに trimEnd
がありました。打ち込んでみると "use dropRightInPlace instead"
と怒られました。 dropRightInPlace
の実装を見てみると、こいつだぁ!となったので使用してみたところ、期待通りの速度が出ました。嬉しい。
自分としては pop
みたいな、要素を 一つだけ 削除する高速なmethodが、mutableな ArrrayBuffer
にはあればもっとサクッと書けたのにと思うばかりです。……実はあったりするんですかね?