I am trying to understand how is the Listbuffer implemented.
@SerialVersionUID(3419063961353022662L)
final class ListBuffer[A]
extends AbstractBuffer[A]
with Buffer[A]
with GenericTraversableTemplate[A, ListBuffer]
with BufferLike[A, ListBuffer[A]]
with ReusableBuilder[A, List[A]]
with SeqForwarder[A]
with Serializable
{
override def companion: GenericCompanion[ListBuffer] = ListBuffer
import scala.collection.Traversable
import scala.collection.immutable.ListSerializeEnd
/** Expected invariants:
* If start.isEmpty, last0 == null
* If start.nonEmpty, last0 != null
* If len == 0, start.isEmpty
* If len > 0, start.nonEmpty
*/
private var start: List[A] = Nil
private var last0: ::[A] = _
private var exported: Boolean = false
private var len = 0
...
}
The first question is, I couldn't understand the syntax ::[A] = _ from private var last0. It looks like a type though but what does it mean by ::[A] and why it requires _ on the RHS? It seems that the syntax is used to represent the last element of the List, but how does it work?
The second questions is related to the fact that ListBuffer utilizes Var tail not the Val tail (even it is immutable) to make the addition fast. How can the above += function helps it achieve faster addition???
def += (x: A): this.type = {
if (exported) copy()
if (isEmpty) {
last0 = new :: (x, Nil)
start = last0
} else {
val last1 = last0
last0 = new :: (x, Nil)
last1.tl = last0
}
len += 1
this
}
The last question is about how the addition of ListBuffer works. It seems that start points to last0 all the time after the empty ListBuffer is filled with the first element and the start doesn't change until it becomes empty again. And the addition after the first one, changes the tail of the list to the new List created by below code lines.
val last1 = last0
last0 = new :: (x, Nil)
last1.tl = last0
it looks like the tail of the original list last0 is changed to the new last0 which contains the x, but it seems that this code doesn't really extend the List pointed to by the start. How does it work..? It seems that assigning last0 to the last1.tl appends List(x) to the List pointed to by the start, but I couldn't understand how does it work.
If possible could you explain how the start, last0, last1 will be changed with the input sequence += 1, += 2, += 3, etc?