Начиная с версии 2.12.8 текущей документации , хвост List постоянен, а хвост ListBuffer линейен.Однако, глядя на исходный код , похоже, что для функции tail нет перезаписи, и в большинстве случаев использования (например, удаление элемента head) явно вызывается функция хвоста List.Поскольку ListBuffer, кажется, немного больше, чем обертка List с длиной var и указателем на последний элемент, почему он линейный?
Я рассчитал оба метода, и на самом деле кажется, что хвост List постоянен, а хвост ListBufferдействительно линейно:
import scala.collection.mutable
import scala.collection.immutable
val immutableList: immutable.List[Int] = (1 to 10000).toList
val mutableListBuffer: mutable.ListBuffer[Int] = mutable.ListBuffer.empty[Int] ++= (1 to 10000).toList
// Warm-up
(1 to 100000).foreach(_ => immutableList.tail)
(1 to 100000).foreach(_ => mutableListBuffer.tail)
// Measure
val start = System.nanoTime()
(1 to 1000).foreach(_ => immutableList.tail)
val middle = System.nanoTime()
(1 to 1000).foreach(_ => mutableListBuffer.tail)
val stop = System.nanoTime()
println((middle - start) / 1000)
println((stop - middle) / 1000)
Результаты были, как задокументировано:
1076
86010
Однако, если вы используете такие функции, как remove (0), которые используют хвост List, он будет постоянным сследующие результаты:
1350
1724
Я ожидаю, что сложность линейности возникает из-за построения целого нового списка для возврата, но, поскольку внутренняя структура является списком, почему бы не вернуть хвост списка?