ListBuffer
может эффективно присоединить элемент до конца и затем преобразовать в List
.головоломка новичка об исходном коде + = метод класса ListBuffer в Scala
Я изучил исходный код метода добавления ListBuffer
(+=
), но было трудно понять его работу. Детальный исходный код: here.
Выдержки Исходный код:
final class ListBuffer[A] extends AbstractBuffer[A] {
private var start: List[A] = Nil
private var last0: ::[A] = _
private var exported: Boolean = false
private var len = 0
def += (x: A): this.type = {
if (exported) copy()
if (isEmpty) {
last0 = new :: (x, Nil)
start = last0
} else {
val last1 = last0 // last1 is a local variable, is it necessary here?
last0 = new :: (x, Nil)
last1.tl = last0 //
}
len += 1
this
}
}
В else
части, локальная переменная last1
определена и впоследствии построена, чтобы содержать в конце несколько элементов. last0
всегда указывает на последнюю ячейку.
Значит, last1
необходимо здесь? В конце концов, после блокировки он будет недоступен. Я не могу понять, почему автор должен определить last1
здесь.
Спасибо. Все еще запутано. Почему «нужна временная переменная для хранения недавно созданного последнего элемента»? 'last0 = new :: (x, Nil)' будет хранить последнюю ячейку в поле класса 'last0'. Но 'last1' - это только локальная переменная, она исчезает после блока кода' else'. – Spring
Недостаточно переместить 'last0'; вам также понадобится «tl» текущего предпоследнего элемента, чтобы указать на только что созданный элемент. Итак 'last0.tl = new :: (x, Nil); last0 = last0.tl' будет отлично работать, используя 'tl' вместо' last1'. Выбор между ними - это вопрос вкуса и/или тестов производительности. – alf
Я обнаружил, что эта реализация метода '+ =' имеет некоторые проблемы. Приложенные элементы не могут быть сохранены в 'start'. Вот демонграмма выполнения: (1) 'val t = new ListBuffer [Int]'; (2) 't + = 1' // {' start = List (1) ',' last0 = List (1) '}; (3) 't + = 2'; {'start = List (1)', 'last0 = List (1)'} (4) 't.toList' {' List (1) '}. – Spring